如何更新DataTable中的所有自动增量列?

时间:2009-09-08 10:30:52

标签: c# ado.net datatable auto-increment

我有一个带有“Id”列的DataTable,它是我们的SQL Server 2005数据库中的标识列。此列的AutoIncrement属性设置为true。我没有用DB中的数据填充表格,因为我只将它用于插入,因此它从1开始分配伪造的ID。

但是在我调用tableAdapter.Update()之后,我想在该列中包含数据库分配的REAL ID。

由于某种原因,只有第一行得到更新,其余的都没有。 此表使用级联DataRelation(层次结构)引用自身,并且还更新对第一行的引用。

请告诉我如何相应地更新所有ID。

提前致谢!

INSERT语句:

INSERT INTO Components (ComponentId, OrderNo, SerialNo) 
VALUES (@ComponentId, @OrderNo, @SerialNo) 

这里是组件表的架构:

Id BIGINT PK, 
ComponentId BIGINT FK, 
OrderNo int, 
SerialNo int 

请注意,Id列的名称为“Id”,“ComponentId”是FK参考列。

4 个答案:

答案 0 :(得分:4)

以前这很容易。您只需将Column.AutoIncrementSeed和Column.AutoIncrementStep BOTH设置为“-1”即可。这样,添加的新行将具有-1,-2等ID。然后,您的存储过程或TSQL代码将只是:

UPDATE Table
SET 
    Col1 = @Col1
    Col2 = @Col2
WHERE (ID = @ID) -- If this is -1, -2, etc, it won't update

IF (@@ROWCOUNT = 0)
    BEGIN
    INSERT INTO Table(Col1, Col2) VALUES(Col1, Col2)
    SET @ID = SCOPE_IDENTITY();  -- @ID would now change from -1 to 1, 2, 3, etc.
END

然而,微软在他们的infinte智慧中用ADO.NET 4.0改变了这一切。我不确定它何时发生了变化,但它们现在在AutoIncrement列上有一个底层私有字段,它存储该列的当前值。所以,让我们说在数据库中,最后插入的值为“52”,好吧,现在它将隐藏在AutoIncrement列中。现在这会导致多用户应用程序出现巨大问题,因为它从最后一个AutoIncrement值开始向后计数,所以我再也不能再使用“-1”技巧了。我甚至试图采用反思来改变这种情况,但这并不好。我讨厌微软在ADO.NET中打破了这个问题,但是他们坚持“不,我们不会修复错误X [这不会真正影响任何用户]但我们将实施一些全新的东西,这将搞砸所有你工作过的代码“。

答案 1 :(得分:0)

在执行Fill方法之前,创建一个带有自动增量的数据列,

编辑:

    SqlConnection cn = new SqlConnection(@"Connection_String");
    SqlDataAdapter adp;
    SqlCommandBuilder cb;
    DataTable dt;

    private void Form3_Load(object sender, EventArgs e)
    {
        adp= new SqlDataAdapter("select * from temp", cn);
        cb = new SqlCommandBuilder(adp);
        dt = new DataTable();
        dt.Columns.Add("SrNo", typeof(int));
        dt.Columns[0].AutoIncrement = true;
        dt.Columns[0].AutoIncrementSeed = 1;
        dt.Columns[0].AutoIncrementStep = 1;

        adp.Fill(dt);
        dataGridView1.DataSource = dt;
    }
    private void button1_Click(object sender, EventArgs e)
    {
        adp.Update(dt);
    }  

答案 2 :(得分:0)

您必须从SQL返回Identity。但我不再确定语法了

尝试

INSERT INTO Components (ComponentId, OrderNo, SerialNo) 
VALUES (@ComponentId, @OrderNo, @SerialNo);
SET @ComponentId = SCOPE_IDENTITY()

OR

INSERT INTO Components (ComponentId, OrderNo, SerialNo) 
VALUES (@ComponentId, @OrderNo, @SerialNo);
SELECT SCOPE_IDENTITY()

答案 3 :(得分:0)

问题在于上面提到的DataRelation。出于某种原因,由于这个DataRelation,“子”行没有插入数据库中,并且它们的ID没有更新到实际ID,尽管DataTable有“刷新数据表”检查(在配置/高级设置中) )。

我删除了DataRelation并手动完成了所有工作。以下代码为我做了诀窍:

ComponentsTableAdapter cta = new ComponentsTableAdapter();                    
foreach (UpdaterDataSet.ComponentsRow r in uds.Components.Rows)
{                    
   long origId = r.Id;
   cta.Update(r);

   foreach (UpdaterDataSet.ComponentsRow s in uds.Components.Rows)
   {
      if (s.Id != r.Id && !s.IsComponentIdNull() && s.ComponentId == origId)
         s.ComponentId = r.Id;
   }                 
}