DataAdapter不更新源

时间:2012-08-13 10:39:12

标签: c# .net ado.net dataadapter

我在使用DataAdapter时遇到了一个问题,我希望有人可以提供帮助。基本上我正在创建一个系统,如下所示:

  1. 使用DataAdapters从数据源(MS-Access,SQL Server或Excel)读取数据,转换为数据表并插入本地SQL Server数据库。这个位工作正常。 SQL Server表有一个PK,它是一个标识字段,自动增量设置为on。
  2. 后续数据加载从源中读取数据并将其与我们已有的数据进行比较。如果记录丢失则添加(这很好)。如果记录不同则需要更新(这不起作用)。
  3. 在进行差异数据加载时,我创建了一个数据表,该表从目标表(SQL服务器)读取模式,并确保它具有相同的列等。
  4. 目标表中的PK是第0列,因此在插入记录时,将设置第1列以后的所有值(如上所述,这非常有效)。我没有更改我添加的项目的行状态。数据表中的PK设置正确,我可以确认。
  5. 更新数据时,我将第0列(PK列)设置为我正在更新的记录的值,并将所有列设置为与源数据相同。
  6. 对于更新的记录,我在行上调用AcceptChanges和SetModified以确保(我认为)应用程序调用了正确的方法。
  7. 使用命令构建器
  8. 使用SelectCommand和UpdateCommand设置DataAdapter

    当我运行时,我使用SQL事件探查器跟踪它,并且可以看到插入命令正在正确运行,但更新命令根本没有运行,这是问题的症结所在。作为参考,插入表将类似于以下

    PK   Value1    Value 2    Row State
    ==   ======    =======    =========
    124   Test1     Test 2    Added
    123   Test3     Test4     Updated
    

    要注意的事情......

    • 我已经通过将要更改的行加载到数据表中,更改了一些列字段并运行更新来测试了这一点。但是,这对我的解决方案来说是不切实际的,因为数据大于1Gb,因此我无法简单地将其加载到数据表中而不会产生巨大的性能损失。我正在做的是创建最多500行的数据表并运行更新。初始数据加载期间的测试表明,这在内存使用和性能方面是最有效的。运行每个批次后,将清除数据表。

    任何关于我在哪里出错的想法?​​

    提前致谢

    安德鲁

    ==========更新==============

    以下是创建插入/更新行的代码

        private static void AddNewRecordToDataTable(DbDataReader pReader, ref DataTable pUpdateDataTable)
        {
    
            // create a new row in the table
    
            DataRow pUpdateRow = pUpdateDataTable.NewRow();
    
            // loop through each item in the data reader - setting all the columns apart from the PK
    
            for (int addCount = 0; addCount < pReader.FieldCount; addCount++)
            {
                pUpdateRow[addCount + 1] = pReader[addCount];
            }
    
            // add the row to the update table
    
            pUpdateDataTable.Rows.Add(pUpdateRow);
    
        }
    
        private static void AddUpdateRecordToDataTable(DbDataReader pReader, int pKeyValue,
                                                       ref DataTable pUpdateDataTable)
        {
            DataRow pUpdateRow = pUpdateDataTable.NewRow();
    
            // set the first column (PK) to the value passed in
    
            pUpdateRow[0] = pKeyValue;
    
            // loop for each row apart from the PK row
    
            for (int addCount = 0; addCount < pReader.FieldCount; addCount++)
            {
                pUpdateRow[addCount + 1] = pReader[addCount];
            }
    
            // add the row to the table and then update it
    
            pUpdateDataTable.Rows.Add(pUpdateRow);
            pUpdateRow.AcceptChanges();
            pUpdateRow.SetModified();
        }
    

    以下代码用于实际执行更新:

        updateAdapter.Fill(UpdateTable);
        updateAdapter.Update(UpdateTable);
        UpdateTable.AcceptChanges();
    

    以下用于创建数据表以确保其具有与源数据相同的字段/数据类型

        private static DataTable CreateDataTable(DbDataReader pReader)
        {
            DataTable schemaTable = pReader.GetSchemaTable();
            DataTable resultTable = new DataTable(<tableName>); // edited out personal info
            // loop for each row in the schema table
    
            try
            {
    
                foreach (DataRow dataRow in schemaTable.Rows)
                {
    
                    // create a new DataColumn object and set values depending
                    // on the current DataRows values
    
                    DataColumn dataColumn = new DataColumn();
                    dataColumn.ColumnName = dataRow["ColumnName"].ToString();
                    dataColumn.DataType = Type.GetType(dataRow["DataType"].ToString());
                    dataColumn.ReadOnly = (bool)dataRow["IsReadOnly"];
                    dataColumn.AutoIncrement = (bool)dataRow["IsAutoIncrement"];
                    dataColumn.Unique = (bool)dataRow["IsUnique"];
    
                    resultTable.Columns.Add(dataColumn);
                }
            }
            catch (Exception ex)
            {
                message = "Unable to create data table " + ex.Message;
                throw new Exception(message, ex);
            }
    
            return resultTable;
        }
    

1 个答案:

答案 0 :(得分:1)

如果有人感兴趣我确实设法绕过问题,但从未设法让数据适配器工作。基本上我所做的如下:

  • 使用索引和字段值列表作为成员
  • 创建对象列表
  • 读入已更改的行并存储源数据中的值(即将覆盖对象中当前值的值)。另外,我创建了一个逗号分隔的索引列表
  • 当我完成后,我在sql IN语句中使用逗号分隔列表来返回行并将它们加载到我的数据适配器中
  • 对于每一个,我对索引运行LINQ查询并提取新值,更新数据集。这会将行状态设置为已修改
  • 然后我运行更新并正确更新行。

这不是最快或最好的解决方案,但它确实有效并允许我批量运行更改。

由于

安德鲁