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

时间:2013-06-27 20:58:58

标签: c# linq entity-framework linq-to-objects

假设我们有这两个类:

class GenericFoo
{
   public Guid ID;
   ...
}

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

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

现在,我有一个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-&gt;特殊转换器,然后尝试创建IComparer只是为了使用Except

我的问题是:

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

2 个答案:

答案 0 :(得分:0)

现在,这是一个很长的镜头,因为它非常深奥,但是你想要一个没有实际关系的外部联接。你可以尝试:

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

答案 1 :(得分:-1)

这可能适用于两种情况:

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