数据表联合
本文关键字:数据表 | 更新日期: 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>();