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> g
和DbSet<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
我的问题是:
- 有没有更好的方法来解决这个问题,只讨论对对象的linq
- 在实体框架的背景下,解决这一问题的最快方法是什么
现在,这是一个很长的机会,因为它非常深奥,但你想要一个由那些没有实际关系的人过滤的外部联接。你可以试试:
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));