使用以下内容时,我会得到重复的行:
DataTable dt = list.AsEnumerable().Distinct().CopyToDataTable();
为什么Distinct()
不起作用?
我的数据表结构:
serial,doc_content,doc_name,selected
int ,Byte[] ,string ,int
答案 0 :(得分:2)
您在一系列数据行上调用Distinct()
。我不相信DataRow
会覆盖Equals
,因此任何两个DataRow
对象都会比较为不相等。
您需要先将IEqualityComparer<DataRow>
传递给Distinct()
,或者先将项目投射到另一种类型(例如,已实现相等比较的匿名类型)并调用Distinct()
新序列。
如果您想继续使用DataRow
,那么实现相等比较器可能最简单。虽然DataRowComparer.Default
看起来很有希望(之前我没有意识到),但由于byte[]
字段,可能在您的特定情况下不起作用。
我个人喜欢尽快将数据转换为更具体的类型,但是YMMV。请注意,如果您将整个DataTable
投影到更具体的类型,则可以将Select
部分写为Where
子句:
var list = table.AsEnumerable()
.Select(row => new { Serial = row.Field<string>("serial"),
ContentBase64 = Convert.ToBase64String(row.Field<byte>("doc_content")),
Name = row.Field<string>("doc_name"),
Selected = row.Field<int>("selected") })
.Where(x => x.Selected == 1)
.Distinct()
.ToList();
请注意,我正在将内容转换为base64字符串,以便相等比较简单。这不是最有效的方法,但 很容易:)如果你不需要内容,你就可以摆脱这一点。
答案 1 :(得分:2)
Distinct
将比较对象引用,因为DataRow
不会覆盖Equals
中的默认GetHashCode
和object
方法,以便将存储的值存入帐户行。
有Enumerable.Distinct的重载,允许您指定自己的相等比较器,并且有一个DataRowComparer类实现所需的IEqualityComparer<DataRow>
接口。
然后您可以像这样使用它:
var distinct = list.AsEnumerable()
.Distinct(DataRowComparer.Default)
.CopyToDataTable();