【问题标题】:Get id when inserting new row using TableAdapter.Update on a file based database在基于文件的数据库上使用 TableAdapter.Update 插入新行时获取 id
【发布时间】:2010-05-12 14:20:18
【问题描述】:

我有一个数据库表,其中有一个字段,称为 ID,是一个自动递增整数。 使用 TableAdapter,我可以读取和修改现有行以及创建新行。

但是,如果我尝试修改新插入的行,则会收到 DBConcurrencyException:

 OleDbConnection conn = new OleDbConnection(@"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=Shift.mdb;Persist Security Info=True");
 ShiftDataSetTableAdapters.ShiftTableAdapter shiftTA = new ShiftDataSetTableAdapters.ShiftTableAdapter();
 shiftTA.Connection = conn;

 ShiftDataSet.ShiftDataTable table = new ShiftDataSet.ShiftDataTable();
 ShiftDataSet.ShiftRow row = table.NewShiftRow();
 row.Name = "life";
 table.Rows.Add(row);
 shiftTA.Update(row); // row.ID == -1
 row.Name = "answer"; // <-- all fine up to here
 shiftTA.Update(row); // DBConcurrencyException: 0 rows affected

另外一个问题,是否有任何静态类型的 NewShiftRow() 方法我可以使用,这样我就不必在每次想要插入新行时创建表。

我猜代码中的问题来自第一次 Update() 调用后仍为 -1 的 row.ID。插入成功,并且在数据库中该行具有有效的 ID 值。

如何获取该 ID 以便继续第二次更新调用?

更新:

看起来这可以使用this setting 自动完成。 但是根据msdn social上的回答,OLEDB驱动不支持这个功能。

不知道从哪里开始,使用 oledb 以外的其他东西?

更新:

试过SQLCompact,发现跟limitation一样,不支持多语句。

最后一个问题:是否有任何简单的(基于单个文件的)数据库可以让您获取插入行的值。

【问题讨论】:

标签: c# database sql-server-ce jet


【解决方案1】:

试试这个 http://support.microsoft.com/kb/815629 ,示例代码在 VB.NET 中。

或者,如果 MS Access 中接受多行查询,并且它具有用于检索最后一个 id 的内置函数/变量,请使用此(尽管数据库是 SQLite):anyway see why I get this "Concurrency Violation" in these few lines of code??? Concurrency violation: the UpdateCommand affected 0 of the expected 1 records,尝试谷歌搜索该函数

[编辑:在我的机器上工作,我没有 SQL Server Compact,但我没有使用多语句]

public Form1()
{
    InitializeComponent();


    var c = Connect();

    var da = new SqlDataAdapter("select emp_id, emp_firstname, emp_lastname from emp where 1 = 0", c);



    var b = new SqlCommandBuilder(da);

    var getIdentity = new SqlCommand("SELECT CAST(@@IDENTITY AS INT)", c);

    da.InsertCommand = b.GetInsertCommand();
    da.UpdateCommand = b.GetUpdateCommand();
    da.DeleteCommand = b.GetDeleteCommand();
    da.RowUpdated += (xsender, xe) =>
    {
        if (xe.Status == UpdateStatus.Continue && xe.StatementType == StatementType.Insert)
        {
            xe.Row["emp_id"] = (int)getIdentity.ExecuteScalar();
        }
    };


    var dt = new DataTable();
    da.Fill(dt);

    var nr = dt.NewRow();
    nr["emp_firstname"] = "john";
    nr["emp_lastname"] = "lennon";


    var nrx = dt.NewRow();
    nrx["emp_firstname"] = "paul";
    nrx["emp_lastname"] = "mccartney";


    dt.Rows.Add(nr);
    dt.Rows.Add(nrx);

    da.Update(dt);

    dt.AcceptChanges();


    nrx["emp_lastname"] = "simon";
    da.Update(dt);

    nr["emp_lastname"] = "valjean";
    da.Update(dt);

}



SqlConnection Connect()
{
    return new SqlConnection(@"data source=.\SQLEXPRESS;Database=Test;uid=sa;pwd=hey");
}

【讨论】:

  • 我喜欢这个想法,但我还没有时间研究这个,但我会的。我认为这将适用于我当前的自定义 DataSet/Table/Rows。
【解决方案2】:

为什么不选择 MAX(RowId),因为您的 RowId 应该为每个 INSERT 递增?这对你来说可能吗?

至于您的最终答案,SQLite 可能是您的完美工具。但愿如此!它有自己的 .NET 数据提供程序,因此不需要 OLEDB 或 ODBC 提供程序。

【讨论】:

  • 我很小心地寻找最大值,因为另一个应用程序可能在两者之间插入了一条新记录。在我的具体情况下,已知数据是唯一的,因此对所有列值的完整搜索解决了到目前为止的问题。
  • 你说得对,Phq,选择 Max(Id) 并不是一个非常巧妙的解决方案,而且它基本上可以完成工作。但是,正如 Micheal Buen 的回答中所述,我不知道 SQL Server 之外的 @@IDENTITY 。这就是解决方案! =)
猜你喜欢
  • 2016-06-15
  • 2012-07-26
  • 1970-01-01
  • 2020-01-19
  • 2020-07-18
  • 2023-03-24
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
相关资源
最近更新 更多