2012-08-22 25 views
1

有人可以将它转换为C#LINQ吗?在列表中查找缺失的项目<T>

SELECT * 
FROM vf 
     LEFT JOIN dbvf 
     ON  vf.sid =dbvf.sid 
     AND vf.cid =dbvf.cid 
WHERE dbvf.sid IS NULL 

两个VF和dbvf是List<T>。 sid和cid是整数。

我想要做的是在vf中找到在dbvf中缺少的项目。

+0

如果dbfv.sid为null,为什么它甚至在连接标准中?另外,linqpad是你的朋友! –

回答

1

试试这个

    var ret = from p1 in vf 
           join p2 in dbvf 
           on p1.sid equals p2.sid && p1.cid equals p2.cid into g 
           from p2 in g.DefaultIfEmpty() 
           where p2 == null 
           select new {vf=p1, dbvf=p2} 

或这种简单

vf.Except(dbvf); 
+0

我实现基于http://msdn.microsoft.com的IEquatable后/en-us/library/bb300779.aspx,vf.Except(dbvf);工作:) – developer747

+0

好...简单而原始:) – innovia

+0

@Tiz,你的连接语法不完全正确。你只能有一个'equals','equals'左边的表达式只能引用你的'p1'范围变量;类似地,右边的表达式只能引用你的'p2'范围变量。解决这个连接问题最简单的方法就是使用匿名类型,就像我在答案中所做的那样。 – devgeezer

1

类似下面

from dbvf in dbvfs 
from vf in vfs 
where vf.sid == dbvf.sid && vf.cid == dbvf.cid 
where dbvf.sid == null 
select new { dbvf = dbvf, vf = vf} 
+0

dbvf.sid是一个int。所以它会抛出一个错误“Warning as Error:表达式的结果总是'false',因为'int'类型的值永远不会等于'int'类型的'null'。 “ – developer747

+0

@ developer747这是说,dbvf.sid == null不代表什么,这个值是否可以为空? –

+0

不可空值。在SQL中,我该怎么做。 – developer747

0

尝试是这样的:

var query = 
    from v in vf 
    join d in dbvf 
    on new { v.sid, v.cid } 
    equals new { d.sid, d.cid } into gj 
    where !gj.Any() 
    select v; 

如前所述,您的目的是做一个“除外”。我已经回答了如何用左连接语义来做到这一点。

var query = 
    from v in vf 
    join d in dbvf 
    on new { v.sid, v.cid } 
    equals new { d.sid, d.cid } into gj 
    from d in gj.DefaultIfEmpty() 
    where d == null 
    select v; 

这里使用的匿名类型似乎是黑魔法的门外汉。然而,编译器创建匿名类型(实际上它只是一种类型),其具有名为sidcid的两个属性,并提供EqualsGetHashCode的实现,Join将在其实现中使用。我在into子句中选择gj是因为引入into会导致编译器执行GroupJoin而不是定期调用Join

我可以添加到查询通过添加from d in gj.DefaultIfEmpty()条款,恢复了先前由into条款隐藏在d范围变量得到类似的感觉,你的SQL样品。现在我可以添加where d == null子句,与原始SQL几乎达到同等水平。

这个匿名类型介绍是您可能需要再次使用的东西,如果您想要通过sidcid这两个组执行其他操作(例如组)。