无法在C#WinForm应用程序中写入数据库

时间:2013-07-03 14:37:17

标签: c# winforms ms-access

我对专业编程相对缺乏经验,但我正在尝试编写一个与MS Access数据库接口的程序。基本上我正在收集表单中的信息,并尝试在每个条目的新行传递信息。我有一个开放的OleDbConnection,我的测试显示我能够看到哪个行将有新条目,但是当我点击提交按钮时,catch中没有显示错误,但数据库保持不变。我最初在click方法中调用了一个代码,但是我只是将代码放到了事件处理程序中,以验证问题不在于调用。

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();
        }

    }

关于为什么不写作的任何想法都将不胜感激。

2 个答案:

答案 0 :(得分: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 方法似乎都返回字符串。请记住,这些方法应返回与您要编写的基础数据库字段兼容的值

答案 1 :(得分:1)

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

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