我有两个集合,这两个集合都有属性电子邮件。我需要在第一个列表中获得电子邮件不存在于第二个列表中的项目列表。对于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 };

但我不能加入,因为我需要的差异和连接将失败。我需要一些方法使用包含或存在我相信。我只是还没有找到这样做的例子。


当前回答

您需要使用Except运算符。

var answer = list1.Except(list2);

更好的解释在这里:https://learn.microsoft.com/archive/blogs/charlie/linq-farm-more-on-set-operators

注意:此技术仅适用于基本类型,因为您必须实现一个IEqualityComparer才能对复杂类型使用Except方法。

其他回答

为简单起见,使用int类型List的示例。

List<int> list1 = new List<int>();
// fill data
List<int> list2 = new List<int>();
// fill data

var results = from i in list1
              where !list2.Contains(i)
              select i;

foreach (var result in results)
    Console.WriteLine(result.ToString());

在使用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查询中可以有两个from。下面是一个使用列表的完整工作示例。每个类Foo和Bar都有一个Id。Foo通过Foo. barid对Bar有一个“外键”引用。程序选择所有未链接到相应Bar的Foo。

class Program
{
    static void Main(string[] args)
    {
        // Creates some foos
        List<Foo> fooList = new List<Foo>();
        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<Bar> barList = new List<Bar>();
        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; }
}

您需要使用Except运算符。

var answer = list1.Except(list2);

更好的解释在这里:https://learn.microsoft.com/archive/blogs/charlie/linq-farm-more-on-set-operators

注意:此技术仅适用于基本类型,因为您必须实现一个IEqualityComparer才能对复杂类型使用Except方法。

在第一个列表中,电子邮件在第二个列表中不存在。

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

如果组为空,就不能做一个外部连接,只从第一个列表中选择项目吗?喜欢的东西:

Dim result = (From a In list1
              Group Join b In list2 
                  On a.Value Equals b.Value 
                  Into grp = Group
              Where Not grp.Any
              Select a)

我不确定这是否会以任何一种有效的方式与实体框架一起工作。