【问题标题】:How to update all the autoincrement columns in a DataTable?如何更新 DataTable 中的所有自动增量列?
【发布时间】:2009-09-08 10:30:51
【问题描述】:

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

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

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

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

提前致谢!

插入语句:

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

这里是组件表的架构:

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

请注意,Id 列的名称是“Id”,“ComponentId”是 FK 引用列。

【问题讨论】:

  • 您能否发布属于插入命令的插入语句?
  • 当然:插入组件(ComponentId、OrderNo、SerialNo)值(@ComponentId、@OrderNo、@SerialNo)。这里是组件表的架构:Id BIGINT PK, ComponentId BIGINT FK, OrderNo int, SerialNo int 注意 Id 列的名称是“Id”,“ComponentId”是 FK 引用列。

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


【解决方案1】:

这曾经很容易。您只需将 Column.AutoIncrementSeed 和 Column.AutoIncrementStep 都设置为“-1”。这样,添加的新行的 ID 将为 -1、-2 等。那么您的存储过程或 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

但是,Microsoft 以其无穷的智慧通过 ADO.NET 4.0 使这一切变得更糟。我不确定它何时更改,但他们现在在 AutoIncrement 列上有一个底层私有字段,该字段存储该列的当前值。因此,假设在数据库中,最后插入的值为“52”,那么现在将隐藏在 AutoIncrement 列中。现在这会导致多用户应用程序出现巨大问题,我不能再使用“-1”技巧了,因为它从最后一个 AutoIncrement 值开始倒数。我什至试图通过反思来改变这一点,但这并没有什么好处。我讨厌微软在 ADO.NET 中打破了这一点,但他们坚持他们的口头禅:“不,我们不会修复 bug X [这不会真正影响任何用户],但我们将实施一些全新的东西,这会搞砸你曾经工作过的所有代码”。

【讨论】:

    【解决方案2】:

    在执行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);
        }  
    

    【讨论】:

    • 我不叫填充,只叫更新。 DataTable 仅用于插入。但是在我调用 Update 之后,我需要真正的 ID。
    【解决方案3】:

    您必须从 SQL 中返回身份。但是我不确定确切的语法了

    试试

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

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

    【讨论】:

      【解决方案4】:

      问题出在提到的 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;
         }                 
      }
      

      【讨论】:

      • 是的,但是数据集有什么问题?为什么这种行为首先是可能的? IMO,这只是证明了数据集抽象的漏洞。
      猜你喜欢
      • 2019-10-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-29
      • 2019-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多