【问题标题】:Can a DataSet table be filled with data from two sources?可以用来自两个源的数据填充 DataSet 表吗?
【发布时间】:2016-04-29 09:54:02
【问题描述】:

我有一个DataSet 并从其中的两个来源读取数据。一个来自 XML 文件的表和另一个来自 Firebird SQL 数据库的表。我试图得到的只是一个表,其中包含 XML 文件中的所有列以及单个表中 SQL 数据中的几个字段。两个表中都有相同的唯一键字段,因此可以轻松合并。我想将此表的所有字段绑定到表单上的字段。

是否可能像描述的那样,或者我没有看到有更简单的解决方案来解决我的问题?

编辑: 为了展示我尝试做的一些额外代码。

DataSet dataSet = new DataSet();

DataTable table1 = new DataTable("test1", "test1");
table1.Columns.Add("id");
table1.Columns.Add("name");
table1.Columns[0].Unique = true;

table1.Rows.Add(new object[2] { 1, "name1" });
table1.Rows.Add(new object[2] { 2, "name2" });

DataTable table2 = new DataTable("test2", "test2");
table2.Columns.Add("id");
table2.Columns.Add("thing");
table2.Columns[0].Unique = true;

table2.Rows.Add(new object[2] { 1, "thing1" });
table2.Rows.Add(new object[2] { 2, "thing2" });

dataSet.Tables.Add(table1);
dataSet.Tables[0].Merge(table2, false);

当我运行这段代码时,我得到一个ConstraintException。当我删除 id 字段上的唯一值时,它会用所有需要的列填充列表,但其中一行包含来自 table1 的数据,另一行包含 table2 数据。如何合并它们?

编辑 2: 我尝试在实时数据中使用 PrimaryKey 解决方案,如下所示。

xmlData.Tables[0].PrimaryKey = new[] { xmlData.Tables[0].Columns["usnr"] };
dbData.PrimaryKey = new[] { dbData.Columns["usid"] };
xmlData.Tables[0].Merge(dbData, true, MissingSchemaAction.Add);

xmlData 是来自 XML 文件的 DataSet。它有 id、usnr 和其他一些字段。 dbData 是一个DataTable,其中包含来自 db 的数据,它具有 id、usid、name 和其他一些字段。 id 字段与我的数据无关。正如我使用GetType() 测试的那样,usnr 和 usid 字段都是表中的字符串。

当我现在添加 xmlData.Tables[0].Merge(dbData, true, MissingSchemaAction.Add); 时,它会抛出 DataException

<target>.ID and <source>.ID have conflicting properties: DataType property mismatch.

在写这篇文章时,我意识到两个表中的 id 字段不同,但无论如何我都不需要它们,所以在更改 primaryKey 条目和合并之前删除了该列。现在我得到一个NullReferenceException,里面没有更多信息。表都很好,里面有数据,现在哪里来的异常?

【问题讨论】:

    标签: c# dataset


    【解决方案1】:

    而不是...

    table1.Columns[0].Unique = true;
    table2.Columns[0].Unique = true;
    

    ...添加这些行:

    table1.PrimaryKey = new[] { table1.Columns[0] };
    table2.PrimaryKey = new[] { table2.Columns[0] };
    

    因为合并命令需要知道数据表的主键。仅仅指出哪些列是唯一的是不够的。使用主键,输出将是:

    id name  thing
    == ===== ======
    1  name1 thing1 
    2  name2 thing2 
    

    请注意,要使其正常工作,主键字段必须具有匹配的数据类型名称。如果数据类型不匹配,您会收到一条不错的错误消息。但是,如果名称不匹配,则会引发无法描述的空引用异常。微软本可以在这方面做得更好。

    这意味着在您的情况下,我建议在合并数据表之前重命名 usnrusid

    【讨论】:

    • 答案比解决方案 s.akbari 更好,但是当我尝试将其应用于我的实时数据时,它会向我抛出一些错误。这意味着我使用的字符串 PrimaryKey Fields 不兼容。
    • 你能比一些错误更具体吗?您可以在创建其中一个数据表时通过转换数据类型/列名来使键匹配吗?使用匹配的主键会让生活更轻松。
    • 我有点时间压力,但我稍后会详细解释。所以我最终可以重构它。
    • 哦,我忘了在问题中宣布我的编辑。我如何控制合并哪些字段、更改数据类型或如何使用它们?
    • 谢谢,这就是重点。我更改了 db 查询以将值作为 usnr 返回,现在它按预期工作。感谢您的帮助。
    【解决方案2】:

    您可以为此目的使用 Linq 并像这样加入您的两个 DataTables

    .........
    .........
    dataSet.Tables.Add(table1);
    //dataSet.Tables[0].Merge(table2, false);
    
    var collection = from t1 in dataSet.Tables[0].AsEnumerable()
                     join t2 in table2.AsEnumerable()
                     on t1["id"] equals t2["id"]
                     select new
                     {
                         ID = t1["id"],
                         Name = t1["name"],
                         Thing = t2["thing"]
                     };
    
    DataTable result = new DataTable("Result");
    result.Columns.Add("ID", typeof(string));
    result.Columns.Add("Name", typeof(string));
    result.Columns.Add("Thing", typeof(string));
    
    foreach (var item in collection)
    {
        result.Rows.Add(item.ID, item.Name, item.Thing);
    }
    

    DataGridView 中的结果将是您想要的结果,如下所示:

    dataGridView1.DataSource = result;
    

    【讨论】:

    • 我目前正在使用这个解决方案,因为 Gert Arnold 的回答确实给我带来了一些错误。但是现在你的是我可以用来解决我的问题的最好的。我将其更改为填充具体类而不是匿名类。
    【解决方案3】:

    在这里,您不能将这两个数据表合并在一起。您需要合并这两个表中的数据,每个表都进行迭代。

    创建包含所有列(Id、Name、Thing)的新数据表。然后填充该表以读取其他两个。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 2021-02-18
    • 1970-01-01
    • 2014-11-18
    • 1970-01-01
    • 2020-10-28
    • 1970-01-01
    相关资源
    最近更新 更多