请你检查一下这里有什么问题。
我需要联合此但它返回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>();
答案 0 :(得分:10)
这里的问题是Linq不知道你想比较Name
。相反,它会对所有对象类型执行的操作,它会比较两个不同实例的哈希值。
你需要做的是告诉联盟方法如何比较两个项目。您可以通过创建自定义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>();
时,您需要传入此比较器的实例:
DataRow
有关详细信息,请参阅此处:
http://msdn.microsoft.com/en-us/library/bb358407.aspx
建议:
Linq最适合自定义数据类,DataTable
不是。最好在课堂上有一个实际的Name属性,只有Linq才能真正发光
如果您不需要动态模式的灵活性,则应远离DataTable
并实现类似于您所需的自定义类,因为{{1}}非常臃肿且缓慢。
答案 1 :(得分:4)
如果您的DataTables模式相同,您可以使用现有的DataRowComparer.Default,如下所示:
DataTable dtUnion = dt1.AsEnumerable().Union(dt2.AsEnumerable()).Distinct(DataRowComparer.Default).CopyToDataTable<DataRow>();
当您需要联合更多2个表时,Aggregate函数非常方便,例如:
// 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>();