数据表联合

本文关键字:数据表 | 更新日期: 2023-09-27 18:27:10

您能否检查一下以下内容中出了什么问题。

我需要这个联合,但它返回 6 条记录而不是 5(因为"Amir"出现了两次(

DataTable dt1 = new DataTable();
dt1.Columns.Add(new DataColumn("Name"));
dt1.Rows.Add(dt1.NewRow()["Name"] = "Imran");
dt1.Rows.Add(dt1.NewRow()["Name"] = "Amir");
dt1.Rows.Add(dt1.NewRow()["Name"] = "Asif");
DataTable dt2 = new DataTable();
dt2.Columns.Add(new DataColumn("Name"));
dt2.Rows.Add(dt2.NewRow()["Name"] = "Tandulkar");
dt2.Rows.Add(dt2.NewRow()["Name"] = "Amir");
dt2.Rows.Add(dt2.NewRow()["Name"] = "Sheqwag");
 DataTable dtUnion = dt1.AsEnumerable()
  .Union(dt2.AsEnumerable()).CopyToDataTable<DataRow>();

数据表联合

这里的问题是Linq不知道你想比较Name。相反,它对所有对象类型执行的操作,它比较两个不同实例不同的哈希值。

您需要做的是告诉 Union 方法如何比较两个项目。为此,您可以创建一个自定义IEqualityComparer,该可以按照您想要的方式比较两个数据行。

下面是一个示例实现:

class CustomComparer : IEqualityComparer<DataRow>
{
    #region IEqualityComparer<DataRow> Members
    public bool Equals(DataRow x, DataRow y)
    {
        return ((string)x["Name"]).Equals((string)y["Name"]);
    }
    public int GetHashCode(DataRow obj)
    {
        return ((string)obj["Name"]).GetHashCode();
    }
    #endregion
}

调用Union时,您需要传入此比较器的实例:

var comparer = new CustomComparer();
DataTable dtUnion = dt1.AsEnumerable()
      .Union(dt2.AsEnumerable(), comparer).CopyToDataTable<DataRow>();

有关更多信息,请参阅此处:
http://msdn.microsoft.com/en-us/library/bb358407.aspx

忠告:
Linq 最适合自定义数据类,而DataRow不是。最好在类上有一个实际的 Name 属性,只有这样 Linq 才能真正大放异彩。
如果你不需要动态模式的灵活性,你应该远离DataTable并实现与你需要的完全相似的自定义类,因为DataTable非常臃肿和缓慢。

如果 DataTable 的架构相同,则可以使用现有的 DataRowComparer.Default,如下所示:

DataTable dtUnion = dt1.AsEnumerable().Union(dt2.AsEnumerable()).Distinct(DataRowComparer.Default).CopyToDataTable<DataRow>();

当您需要合并超过 2 个表时,聚合函数非常方便,例如:

// Create a table "template"
DataTable dt = new DataTable();
dt.Columns.Add(new DataColumn("Name"));
// Create a List of DataTables and add 3 identical tables
List<DataTable> dtList = new List<DataTable>();
dtList.AddRange(new List<DataTable>() { dt.Clone(), dt.Clone(), dt.Clone()});
// Populate the 3 clones with some data
dtList[0].Rows.Add("Imran");
dtList[0].Rows.Add("Amir"); 
dtList[0].Rows.Add("Asif");
dtList[1].Rows.Add("Tandulkar");
dtList[1].Rows.Add("Amir");  
dtList[1].Rows.Add("Sheqwag");
dtList[2].Rows.Add("John");
dtList[2].Rows.Add("Sheqwag");
dtList[2].Rows.Add("Mike");
// Union the 3 clones into a single DataTable containing only distinct rows
DataTable dtUnion = dtList
                    .Select(d => d.Select().AsEnumerable())
                    .Aggregate((current, next) => current.Union(next))
                    .Distinct(DataRowComparer.Default)
                    .CopyToDataTable<DataRow>();