在单个LINQ语句中使用.Select和.Where

rob*_*r08 25 c# linq unique distinct

我需要使用LINQ从特定的表中收集Distinct Id.问题是我还需要一个WHERE语句,它应该仅根据我设置的要求过滤结果.不得不如此使用LINQ相对较新,但我或多或少地使用以下代码:

private void WriteStuff(SqlHelper db, EmployeeHelper emp)
{
    String checkFieldChange;
    AnIList tableClass = new AnIList(db, (int)emp.PersonId);
    var linq = tableClass.Items
        .Where(
           x => x.UserId == emp.UserId 
             && x.Date > DateBeforeChanges 
             && x.Date < DateAfterEffective 
             && (
                     (x.Field == Inserted)
                  || (x.Field == Deleted)))
                )
             ).OrderByDescending(x => x.Id);

    if (linq != null)
    {
        foreach (TableClassChanges item in linq)
        {
            AnotherIList payTxn = new AnotherIList(db, item.Id);
            checkFieldChange = GetChangeType(item.FieldName);

            // Other codes that will retrieve data from each item 
            // and write it into a text file
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我试图为var linq添加.Distinct但它仍然返回重复的项目(意味着具有相同的Id).我已阅读了很多网站,并尝试在查询中添加.Select,但.Where子句会中断.还有其他一些文章,其中查询与检索值并将其放在var中的方式有​​所不同.我也尝试使用.GroupBy,但是当使用Id作为键时,我得到"至少一个对象必须实现IComparable".

查询实际上有效,我能够从我需要的规范输出列中的数据,但我似乎无法使.Distinct工作(这是唯一真正缺少的).我尝试创建两个vars,其中一个触发一个不同的调用,然后有一个嵌套的foreach以确保值只是唯一的,但是收集性能影响的数千个记录太多了.

如果我不得不为我的要求覆盖或使用IEnumerable,我也不确定,并且我认为我会问这个问题,以防万一有更简单的方法,或者是否可以同时使用.选择和.工作在一个声明中?

Fla*_*ter 41

你加Select()之后Where()或之前?

之后应该添加它,因为并发逻辑:

 1 Take the entire table  
 2 Filter it accordingly  
 3 Select only the ID's  
 4 Make them distinct.  
Run Code Online (Sandbox Code Playgroud)

如果先执行"选择",则Where子句只能包含ID属性,因为所有其他属性都已被删除.

更新:为清楚起见,此运算符的顺序应该起作用:

db.Items.Where(x=> x.userid == user_ID).Select(x=>x.Id).Distinct();
Run Code Online (Sandbox Code Playgroud)

可能想.toList()在最后添加一个但是可选的:)


Mar*_*ers 11

为了Enumerable.Distinct给你的类型,可以实现工作IEquatable<T>和提供适当的定义EqualsGetHashCode,否则会使用默认的实现:参考平等比较(假设你使用的是引用类型).

从手册:

Distinct(IEnumerable)方法返回一个不包含重复值的无序序列.它使用默认的相等比较器Default来比较值.

默认的相等比较器Default用于比较实现IEquatable泛型接口的类型的值.要比较自定义数据类型,您需要实现此接口并为该类型提供自己的GetHashCode和Equals方法.

在您的情况下,您可能只需要比较ID,但您可能还想比较其他字段,具体取决于两个对象"相同"对您来说意味着什么.

您也可以考虑使用DistinctBymorelinq.

请注意,这只是LINQ to Objects,但我认为这就是您正在使用的内容.

另一种选择是结合GroupByFirst:

 var query = // your query here...
    .GroupBy(x => x.Id)
    .Select(g => g.First());
Run Code Online (Sandbox Code Playgroud)

例如,这也适用于LINQ to SQL.