【问题标题】:DataAdapter not updating sourceDataAdapter 不更新源
【发布时间】:2012-08-09 14:03:55
【问题描述】:

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

  1. 使用 DataAdapter 从数据源(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. DataAdapter 是使用命令生成器通过 SelectCommand 和 UpdateCommand 设置的。

当我运行时,我使用 SQL 分析器对其进行了跟踪,可以看到插入命令正在正确运行,但更新命令根本没有运行,这是问题的症结所在。作为参考,插入表将如下所示

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

需要注意的几件事....

  • 我已经通过将要更改的行加载到数据表中、更改一些列字段并运行更新来测试这一点,这很有效。然而,这对我的解决方案来说是不切实际的,因为数据是 HUGE > 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;
    }

【问题讨论】:

  • 供参考这是3修改和3添加的数据表状态(第1列是PK) 238281;Modified 238298;Modified 238306;Modified 238307;Added 238308;Added 238309;Added
  • 一些代码可以帮助我们识别问题。

标签: c# .net ado.net dataadapter


【解决方案1】:

万一有人感兴趣,我确实设法解决了这个问题,但从未设法让数据适配器工作。基本上我所做的如下:

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

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

谢谢

安德鲁

【讨论】:

    猜你喜欢
    • 2010-12-05
    • 2016-04-16
    • 2011-12-31
    • 2010-09-23
    • 1970-01-01
    • 2014-02-08
    • 2011-12-31
    • 2015-04-23
    • 1970-01-01
    相关资源
    最近更新 更多