使用C#(OleDB)自动增量主键插入新的DataRow

时间:2011-12-20 10:45:27

标签: c# ms-access insert oledb primary-key

我正在尝试使用C#将新的DataRow(本地存储在DataSet中)插入到Access表中。该表也是由此应用程序创建的,有3列:

  • ID(整数,主键,Required设置为No,但我已将其设置为主键)
  • Name(字符串)
  • Money(int)

我当前的代码如下:

        OleDbConnection con = new OleDbConnection();
        OleDbCommand cmd = new OleDbCommand();
        OleDbDataAdapter da;
        DataSet ds = new DataSet();
        DataView dv = new DataView();
        DataRow row;

        string Con = @"Provider=Microsoft.Jet.OLEDB.4.0;" + "Data Source=";
        string path = "V:\\ProjectProgress\\Test.mdb";
        con.ConnectionString = Con + path;

        if (con.State == ConnectionState.Closed)
        {
            con.Open();
        }
        cmd.Connection = con;

        cmd.CommandText = "SELECT ID, Name, Money FROM Test";
        da = new OleDbDataAdapter(cmd);
        da.TableMappings.Add("Table", "Test");
        da.Fill(ds, "Test");

        ds.Tables["Test"].Columns[0].AutoIncrement = true;
        ds.Tables["Test"].Columns[0].AutoIncrementSeed = -1;
        ds.Tables["Test"].Columns[0].AutoIncrementStep = -1;

        dv.Table = ds.Tables["Test"];

        row = ds.Tables["Test"].NewRow();
        row["Name"] = "Huber";
        row["Money"] = 100;

        ds.Tables["Test"].Rows.Add(row);

        string strOLE = "INSERT INTO Test ([Name], [Money]) Values(@Name, @Money)";

        OleDbCommand cmdi = new OleDbCommand(strOLE, con);
        cmdi.Parameters.Add("@Name", OleDbType.VarChar, 25, "Name");
        cmdi.Parameters.Add("@Money", OleDbType.Integer, 4, "Money");


        da.InsertCommand = cmdi;

        da.Update(ds.Tables["Test"]);

        con.Close();

更新时我总是得到一个

  

索引或主键不能包含空值

错误。

Required列的ID值设为Yes,会抛出

  

索引或主键不能包含空值

错误。

如何让Access分配正确的主键以及如何将新值返回到我的数据集中?

据我所知,在某些论坛中使用SCOPE_IDENTITY()是不可能的。

(使用Visual C#Express 2010,Access 2003)

2 个答案:

答案 0 :(得分:1)

以下是完整的工作测试代码来说明该过程。我们需要做的就是提供一个OleDbDataAdapter.SelectCommand,其中包含主键和我们想要更新的列,OleDbCommandBuilder对象将为我们创建INSERT语句:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.OleDb;

namespace oleDbTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string myConnectionString;
            myConnectionString =
                    @"Provider=Microsoft.ACE.OLEDB.12.0;" +
                    @"Data Source=C:\Users\Public\Database1.accdb;";

            using (OleDbConnection con = new OleDbConnection())
            {
                con.ConnectionString = myConnectionString;
                con.Open();

                using (OleDbDataAdapter da = new OleDbDataAdapter())
                using (OleDbCommandBuilder bld = new OleDbCommandBuilder(da))
                {
                    bld.QuotePrefix = "[";  // these are
                    bld.QuoteSuffix = "]";  //   important!

                    da.SelectCommand = new OleDbCommand(
                            "SELECT [ID], [Name], [Money] " +
                            "FROM [Test] " +
                            "WHERE False",
                            con);
                    using (System.Data.DataTable dt = new System.Data.DataTable("Test"))
                    {
                        // create an empty DataTable with the correct structure
                        da.Fill(dt);

                        System.Data.DataRow dr = dt.NewRow();
                        dr["Name"] = "Huber";
                        dr["Money"] = 100;
                        dt.Rows.Add(dr);

                        da.Update(dt);  // write new row back to database
                    }
                }
                con.Close();
            }
            Console.WriteLine();
            Console.WriteLine("Done.");
        }
    }
}

答案 1 :(得分:0)

我首先想到的是,您的问题可能是AutoIncrementSeedAutoIncrementStep都设置为-1的负值。尝试将两者都设置为正值。

[编辑]

第二个想法,您可能想尝试OleDbCommandBuilderMSDN documentation here)。它使用DataSet的列信息自动创建INSERT,UPDATE和DELETE语句。 在我以前的雇主,我们在使用Access时一直使用OleDbCommandBuilder,它就像魅力一样,即使有自动增量字段也是如此。