DataTable 修改后的行数在适配器填充后恢复为 0

Posted

技术标签:

【中文标题】DataTable 修改后的行数在适配器填充后恢复为 0【英文标题】:DataTable Modified row count reverting to 0 after adapter fill 【发布时间】:2012-09-03 10:13:48 【问题描述】:

如果这是一个愚蠢的错误,我们深表歉意 - 但我已经为此苦苦挣扎了几个星期,我不再继续了。

问题是 - 我从基于 DT 的 DS 到 SQL Db 的更新调用只是插入 nerw 记录,而不是更新修改过的记录。

我有一个数据源(httpWebRequested html 表),我会定期调用它并用它更新属于 DataSet 的 DataTable。最初我将它全部解析为第二个 DataTable 并将其与我的 DataSet 表合并 - 但这不起作用,所以目前我只有一个 DataTable 并且要么将新行插入到表中,要么通过迭代源并添加一行来更新现有值数组的时间 - 检查当前行的存在,并更新或插入([Session ID] 是一个 PK,Data[0] 是对应的唯一值):-

                foreach (var row in rows.Skip(1))
            
                //create new list collection
                var data = new List<string>();
                //interate through rows
                foreach (var column in row.Descendants("td"))
                
                    //add data to list from Table
                    data.Add(column.InnerText);
                
                    string strSelect = "[Session ID] = '"+ data[0] +"'";
                    DataRow[] myRow = dt.Select(strSelect);
                    if (myRow.Length == 1)
                    
                        if (myRow[0][2].ToString() != data[2].ToString())
                        
                            myRow[0][2] = data[2];
                        
                        if (myRow[0][3].ToString() != data[3].ToString())
                        
                            myRow[0][3] = data[3];
                        
                        if (myRow[0][4].ToString() != data[4].ToString())
                        
                            myRow[0][4] = data[4];
                        
                        if (myRow[0][5].ToString() != data[5].ToString())
                        
                            myRow[0][5] = data[5];
                        
                        if (myRow[0][7].ToString() != data[7].ToString())
                        
                            myRow[0][7] = data[7];
                        
                    
                    else
                    
                        dt.Rows.Add(data.ToArray());
                    

我在最后也写了一点添加和修改:-

            int modified= 0;
            int added = 0;
            foreach (DataRow dr in pca.chatDataSetG.Tables[0].Rows)
            
                if (dr.RowState == DataRowState.Modified)
                
                    modified++;
                
                if (dr.RowState == DataRowState.Added)
                
                    added++;
                
            

此时 - 计数很好 - 修改后拾取属性已更改和添加的行是正确的。

当我调用我的更新 Db 方法时 - 事情开始出错:-

    public static void updateSqlTable()
    

        string connectionString = "Connection String here";
        string qry = @"select * from chatData";

        SqlConnection conn = new SqlConnection(connectionString);

        try
        
            SqlDataAdapter da = new SqlDataAdapter(qry, conn);
            SqlCommandBuilder sb = new SqlCommandBuilder(da);
            log.Info("Building Queries...");
            da.UpdateCommand = sb.GetUpdateCommand();
            da.InsertCommand = sb.GetInsertCommand();
            da.DeleteCommand = sb.GetDeleteCommand();

            log.Info("Filling Data into Adapter...");
            int modified = 0;
            int added = 0;
            foreach (DataRow dr in pca.chatDataSetG.Tables[0].Rows)
            
                if (dr.RowState == DataRowState.Modified)
                
                    modified++;
                
                if (dr.RowState == DataRowState.Added)
                
                    added++;
                
            
            //This is where the modified count reverts
            da.Fill(pca.chatDataSetG, "Chat");
            modified = 0;
            added = 0;
            foreach (DataRow dr in pca.chatDataSetG.Tables[0].Rows)
            
                if (dr.RowState == DataRowState.Modified)
                
                    modified ++;
                
                if (dr.RowState == DataRowState.Added)
                
                    added++;
                
            
            conn.Open();
            log.Info("Calling Update to DB...");
            int rowseffected = da.Update(pca.chatDataSetG, "Chat");
            log.Info("Update Complete - " + rowseffected + " rows effected........");

        
        catch (Exception ex)
        
            log.Error("Error Updating Db with chat Data", ex);
        
        finally
        
            conn.Close();
        

    

计数正好在填充之前,但之后 - 添加的计数保持不变 - 好,但修改后的计数变为 0 - 坏:(。我尝试了所有形状来看看这里发生了什么 -但老实说 - 我很难过。任何帮助都会非常非常非常感谢。数据库中的行没有反映新的值。

彼得

【问题讨论】:

你在哪里更新数据库?旁注:您不需要手动计算更改,您可以使用DataTable.GetChanges(rowState)。但是,只要您调用DataSet.AcceptChangesDataAdapter.Update(DataSet)RowState 就会得到Unchanged(您可以将DataSet 替换为DataTable)。 在此之后我正在更新 Db:- conn.Open(); log.Info("调用数据库更新..."); int rowseffected = da.Update(pca.chatDataSetG, "Chat"); 【参考方案1】:

您确实在这行代码中重新填充了您的数据集/表

//This is where the modified count reverts
da.Fill(pca.chatDataSetG, "Chat");

在 MSDN DataAdapter 填充中,我认为对所描述的行为有解释

您可以在同一个 DataTable 上多次使用 Fill 方法。如果一个 主键存在,传入的行与匹配的行合并 已经存在。 如果不存在主键,则将传入的行追加到 数据表

IMO 修改的行已与数据库中的原始拥有合并,因此失去其 rowState,而插入的项目已按所述附加。

【讨论】:

这是有道理的,所以它使用 Db 作为主要来源,并用 Db 值覆盖我的修改 - 这意味着我的行数只等于添加时附加的行数。您能否指出一个可能的解决方案的方向 - 我已经尝试从 CB 编写我自己的更新命令替换 - 数据货币问题 - 但是如果在我打电话之前行没有显示为已修改更新 - 那么这无关紧要,因为它们无论如何都不会在更新范围内。仍然不确定要采取什么角度来进行这些行更新。 我会尝试.. 但在请解释为什么你再次调用 da.Fill (..) 之前 - 我不明白吗?! 我误解了 da.Fill 方法的一些基础知识。我只提取了数据-这是第一次推送,我刚刚将其弹出-了解我现在哪里出错了-非常感谢。现在开始看看为什么我会违反货币:) 也发现了这一点,以防其他人得到它 - 我的选择 * 返回了 2 个计算列 - 做了更完整的选择,忽略了这些,它工作正常。阅读出色的远离 commandbuilder 的文章,这很有帮助 - msdn.microsoft.com/en-us/library/ms971491.aspx

以上是关于DataTable 修改后的行数在适配器填充后恢复为 0的主要内容,如果未能解决你的问题,请参考以下文章

C# 如何把一个table的行填充到另一个table

c# 为啥我修改了datatable后,再更新数据库,只是在原来的表中的行往后加,却不是重新写?应该怎么改啊?

Jqgrid:获取应用本地过滤器后的行数

DataTable.Load 显示的行数少于源 DataReader

DataTable 从行中获取修改后的数据

用C语言编写一个矩阵转置的函数,矩阵的行数和列数在程序中由用户输入,请问怎么写,非常感谢