不同的方法重复数据

时间:2013-02-23 12:31:51

标签: c# asp.net linq datatable distinct

使用以下内容时,我会得到重复的行:

 DataTable dt = list.AsEnumerable().Distinct().CopyToDataTable();  

为什么Distinct()不起作用?


我的数据表结构:

serial,doc_content,doc_name,selected
int   ,Byte[]     ,string  ,int

2 个答案:

答案 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中的默认GetHashCodeobject方法,以便将存储的值存入帐户行。

Enumerable.Distinct的重载,允许您指定自己的相等比较器,并且有一个DataRowComparer类实现所需的IEqualityComparer<DataRow>接口。

然后您可以像这样使用它:

var distinct = list.AsEnumerable()
    .Distinct(DataRowComparer.Default)
    .CopyToDataTable();