当前位置:  开发笔记 > 编程语言 > 正文

你会如何使用LINQ进行"不在"查询?

如何解决《你会如何使用LINQ进行"不在"查询?》经验,为你挑选了7个好方法。

我有两个集合,Email在两个集合中都有属性.我需要获取第一个列表中Email第二个列表中不存在的项目列表.使用SQL我只会使用"not in",但我不知道LINQ中的等价物.怎么做的?

到目前为止,我有一个加入,像......

var matches = from item1 in list1
join item2 in list2 on item1.Email equals item2.Email
select new { Email = list1.Email };

但我不能加入,因为我需要差异,加入会失败.我需要一些使用Contains或Exists的方法我相信.我还没有找到一个例子来做到这一点.



1> Echostorm..:

你想要Except运算符.

var answer = list1.Except(list2);

这里有更好的解释:http://blogs.msdn.com/charlie/archive/2008/07/12/the-linq-set-operators.aspx

注意:此技术仅适用于基本类型,因为您必须实现IEqualityComparer才能使用具有复杂类型的Except方法.


使用Except:如果您使用复杂类型列表,那么您必须实现IEqualityComparer ,它使它不那么好
如果你只想比较引用相等或者你已经覆盖了T.Equals()和T.GetHashCode(),那么你不能**实现IEqualityComparer .如果未实现IEqualityComparer ,将使用[EqualityComparer .Default](http://stackoverflow.com/a/17225006/1925996).
@Echostorm(以及其他人阅读),如果你做一个Select to Anonymous对象,HashCode将由属性值决定; `list1.Select(item => new {Property1 = item.Property1,Property2 = item.Property2}).除外(list2.Select(item => new {Property1 = item.Property1,Property2 = item.Property2})); `当您通过仅评估复杂类型的一组值来确定相等性时,这尤其有用.
实际上,下面有人指出,我正确地认为,不需要在LinqToSql场景中实现IEquatityComparor <T,T>或重写对象比较方法。对于,查询将表示为/编译为/表示为SQL;因此将检查值,而不是对象引用。
使用`except`,我能够将LINQ查询从8-10秒加速到半秒

2> Robert Rouse..:

我不知道这对你有帮助,但是......

NorthwindDataContext dc = new NorthwindDataContext();    
dc.Log = Console.Out;

var query =    
    from c in dc.Customers    
    where !(from o in dc.Orders    
            select o.CustomerID)    
           .Contains(c.CustomerID)    
    select c;

foreach (var c in query) Console.WriteLine( c );

从在LINQ的NOT IN子句中SQL由马可·鲁索


LINQ to Entities对我来说很好用.SQL成为WHERE NOT EXISTS(子查询)查询.也许有更新解决了这个问题?
@Robert Rouse - linq to sql中的The Not in cluse链接不再有效.只是一个fyi.
我认为EF的新版本确实支持.Contains,加上这个问题没有标记EF(版本)或LinqToSQL ..所以可能需要在这里讨论问题和答案.

3> StriplingWar..:

对于以一组内存中对象开头并且正在查询数据库的人,我发现这是最好的方法:

var itemIds = inMemoryList.Select(x => x.Id).ToArray();
var otherObjects = context.ItemList.Where(x => !itemIds.Contains(x.Id));

WHERE ... IN (...)在SQL中生成一个nice 子句.



4> Amy B..:

第一个列表中第二个列表中不存在电子邮件的项目.

from item1 in List1
where !(list2.Any(item2 => item2.Email == item1.Email))
select item1;



5> DevT..:

您可以使用Where和Any的组合来查找不在:

var NotInRecord =list1.Where(p => !list2.Any(p2 => p2.Email  == p.Email));



6> 小智..:

您可以将这两个集合放在两个不同的列表中,例如list1和list2.

然后就写

list1.RemoveAll(Item => list2.Contains(Item));

这会奏效.


很好,但是具有从列表中删除元素的副作用。

7> Brett..:

在使用ADO.NET实体框架的情况下,EchoStorm的解决方案也可以完美运行.但我花了几分钟时间绕过它.假设您有一个数据库上下文dc,并希望在表x中找不到表y中未链接的行,则完整的答案答案如下所示:

var linked =
  from x in dc.X
  from y in dc.Y
  where x.MyProperty == y.MyProperty
  select x;
var notLinked =
  dc.X.Except(linked);

回答Andy的评论,是的,在LINQ查询中可以有两个来自.这是一个完整的工作示例,使用列表.每个类Foo和Bar都有一个Id.Foo有一个"外键"引用Bar via Foo.BarId.程序选择未链接到相应Bar的所有Foo.

class Program
{
    static void Main(string[] args)
    {
        // Creates some foos
        List fooList = new List();
        fooList.Add(new Foo { Id = 1, BarId = 11 });
        fooList.Add(new Foo { Id = 2, BarId = 12 });
        fooList.Add(new Foo { Id = 3, BarId = 13 });
        fooList.Add(new Foo { Id = 4, BarId = 14 });
        fooList.Add(new Foo { Id = 5, BarId = -1 });
        fooList.Add(new Foo { Id = 6, BarId = -1 });
        fooList.Add(new Foo { Id = 7, BarId = -1 });

        // Create some bars
        List barList = new List();
        barList.Add(new Bar { Id = 11 });
        barList.Add(new Bar { Id = 12 });
        barList.Add(new Bar { Id = 13 });
        barList.Add(new Bar { Id = 14 });
        barList.Add(new Bar { Id = 15 });
        barList.Add(new Bar { Id = 16 });
        barList.Add(new Bar { Id = 17 });

        var linked = from foo in fooList
                     from bar in barList
                     where foo.BarId == bar.Id
                     select foo;
        var notLinked = fooList.Except(linked);
        foreach (Foo item in notLinked)
        {
            Console.WriteLine(
                String.Format(
                "Foo.Id: {0} | Bar.Id: {1}",
                item.Id, item.BarId));
        }
        Console.WriteLine("Any key to continue...");
        Console.ReadKey();
    }
}

class Foo
{
    public int Id { get; set; }
    public int BarId { get; set; }
}

class Bar
{
    public int Id { get; set; }
}

推荐阅读
保佑欣疼你的芯疼
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有