2013-07-03 57 views
3

我对专业编程相对缺乏经验,但我正在尝试编写一个与MS Access数据库接口的程序。本质上,我正在收集表单中的信息,并尝试为每个条目以新行传递信息。我有一个开放的OleDbConnection,我的测试显示我能够看到哪一行将有新条目,但是当我点击提交按钮时,捕获中没有显示错误,但数据库保持不变。我最初的代码是通过点击事件调用的方法,但我只是将代码带到事件处理程序来验证问题是否与调用不同。在C#WinForm应用程序中写入数据库时​​遇到困难

private void btnSubmit_Click(object sender, EventArgs e) 
    { 

     if (DBConnection.State.Equals(ConnectionState.Closed)) 
     { 
      DBConnection.Open(); 
     } 

     try 
     { 
      MessageBox.Show("Save Data at index: " + intRowPosition.ToString()); 

      OleDbCommand OledbInsert = new OleDbCommand("Insert INTO RetentionTable (DateTime,Center,CSP,MemberID,ContractNumber,RetentionType,RetentionTrigger,MemberReason,ActionTaken,Other) VALUES('" + DateTime.Now.ToString() + "','" + GetCenter("") + "','" + GetName("") + "','" + GetMemberID("") + "','" + GetContractNumber("") + "','" + GetType("") + "','" + GetTrigger("") + "','" + GetReason("") + "','" + GetAction("") + "', + GetOther("")," DBConnection); 

      intRowPosition++; 
     } 

     catch (Exception ex) 
     { 
      MessageBox.Show(ex.Message.ToString()); 
      MessageBox.Show(ex.StackTrace.ToString()); 
     } 
     finally 
     { 
      RefreshDBConnection(); 
     } 

    } 

任何想法,为什么这不写作将不胜感激。

+1

使用'String.Format'使您的查询更易于管理http://msdn.microsoft.com/zh-cn/library/ system.string.format。aspx – Mataniko

+4

那么,你有多个问题,但[**请使用参数**](http://csharp-station.com/Tutorial/AdoDotNet/Lesson06)而不是构建SQL字符串! –

回答

7

上面的代码中存在很多问题。

  • 首先,应执行命令,而不是简单地声明。 (这就是为什么数据库不被修改)
  • 其次,你在发言中使用保留关键字(所以即使您执行的语句,它会失败,并抛出一个异常)
  • 第三,串联字符串以构建命令文本。一个 非常糟糕此举将让您的应用程序容易受到SQL injection攻击
  • 四,连接应使用后关闭

让我试着写一个替换代码

string cmdText = "Insert INTO RetentionTable " + 
       "([DateTime],Center,CSP,MemberID,ContractNumber,RetentionType," + 
       "RetentionTrigger,MemberReason,ActionTaken,Other) " + 
       "VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; 
using(OleDbConnection cn = new OleDbConnection(conString)) 
using(OleDbCommand cmd = new OleDbCommand(cmdText, cn)) 
{ 
    cmd.Parameters.AddWithValue("@p1", DateTime.Now.ToString()); 
    cmd.Parameters.AddWithValue("@p2", GetCenter("")); 
    cmd.Parameters.AddWithValue("@p3", GetName("")); 
    cmd.Parameters.AddWithValue("@p4", GetMemberID("")); 
    cmd.Parameters.AddWithValue("@p5", GetContractNumber("")); 
    cmd.Parameters.AddWithValue("@p6", GetType("")); 
    cmd.Parameters.AddWithValue("@p7", GetTrigger("")); 
    cmd.Parameters.AddWithValue("@p8", GetReason("")); 
    cmd.Parameters.AddWithValue("@p9", GetAction("")); 
    cmd.Parameters.AddWithValue("@p10", GetOther("")); 
    cmd.ExecuteNonQuery(); 
} 

的DATETIME是Access中的保留关键字,因此,如果要将其用于列名称,则需要将其放在方括号中。

字符串串联在MSAccess中是一个不好的做法,但它是其他数据库中的一个致命缺陷,您的代码可用于Sql Injections(在Access中更困难但不是不可能)。如果您使用参数化查询(如在我的示例中),则可以删除Sql Injection问题,但也可以让框架代码将正确的值传递给数据库引擎,并使用日期,字符串和小数位所需的正确格式。

另一个要考虑的问题是没有一个全局的OleDbConnection对象,只是在需要时创建,使用和销毁对象。该Connection Pooling将避免出现性能问题,并在无论出于何种原因

我还想补充一点,你GetXXXXX方法似乎都返回字符串连接失败你的代码将不会从内存泄漏困扰。请记住,这些方法应返回与要写入的基础数据库字段兼容的值。

+0

你可以解释你的第一个项目是如何完成的,你在第二点中引用了哪些保留关键字,以及为什么你的第三个项目是一个坏的移动,以及这个好的移动是什么。可能是这种方式更有效的答案。只是一些建议。 – Tombala

+0

@Tombala,等一下。这是一个很长的回答 – Steve

+0

只是一些事情。首先,(很小)值的字符串有第二个“和”反转。容易修复。我遇到的问题是,它告诉我“名称'conString'在当前上下文中不存在。”怎么能我修复那个呢?再一次,我有点成熟...... – 1337Atreyu

1

它可能是围绕您放入数据库的值的语音标记。尝试改为撇号。

无论如何,我强烈建议将最终的SQL存储在一个字符串中,并将其打印到日志文件或屏幕上,然后将其复制到Access SQL编辑器并尝试运行它。然后你会看到是否有错误以及它是什么。