linq中排除其他类型(+ef)元素的最快、最干净的方法

本文关键字:方法 元素 排除 其他 类型 +ef linq | 更新日期: 2023-09-27 18:20:22

假设我们有这两个类:

class GenericFoo
{
   public Guid ID;
   ...
}
class SpecialFoo
{
   public Guid ID;
   public Guid GenericFooID;
   ...
}

GenericFoo是一种模板类,SpecialFoo可以从中创建。

现在,我有一个DbSet<GenericFoo> gDbSet<SpecialFoo> s。任何SpecialFoo.GenericFooID都可能存在于g中,但也可能丢失。(GenericFoo可能已被删除)。当然,情况恰恰相反。

我想要的是一个电话,以获得缺乏匹配GenericFooID的,类似于:

missing = s.Except(g)

这不起作用,因为Except只适用于相同的类。目前,我已经通过使用一个相当做作的解决方案解决了这个问题:

ExistingIds = g.Select(f=>f.ID);
missing = s.Where(f => !ExistingIds.Contains(s.GenericFooID));

这里的一个主要缺点是我们失去了类型安全性(如果有人错误地键入g并指定了类似的类,就没有办法检查这一点)。我更喜欢IComparer<type1, type2>之类的东西,这样Except调用就可以工作了。

我发现的其他选择是

  • 使用组联接进行"伪左联接",并保持不匹配
  • 将第一个转换为字典、哈希表等,只是为了加快速度
  • 试图创建一个Generic->Special转换器,然后创建一个IComparer,只是为了使用Except

我的问题是:

  1. 有没有更好的方法来解决这个问题,只讨论对对象的linq
  2. 在实体框架的背景下,解决这一问题的最快方法是什么

linq中排除其他类型(+ef)元素的最快、最干净的方法

现在,这是一个很长的机会,因为它非常深奥,但你想要一个由那些没有实际关系的人过滤的外部联接。你可以试试:

from specialFoo in context.SpecialFoos
join genericFoo in context.GenericFoos 
     on specialFoo.GenericFooID equals genericFoo.ID 
     into gj
where !gj.Any()
select specialFoo;

这两种情况都适用:

var missing = s.Where(a => !g.Any(b => b.ID == a.GenericFooID));