2011-10-14 71 views
2

所以我对linq有点问题。我想加盟是一个OUTER JOIN或INNER JOIN,取决于是否值将被过滤在桌子上LINQ中的条件加入

OUTER JOIN:

var query = (from tblA in dc.tblA 
      join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB 
      from tblB in joinedTblB.DefaultIfEmpty() 
      select tblA); 

INNER JOIN:

var query = (from tblA in dc.tblA 
      join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB 
      from tblB in joinedTblB 
      select tblA); 

什么我想要结合这在相同的查询,并通过检查一些条件做一个外部联接或内部联接,如下所示:

var query = (from tblA in dc.tblA 
      join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB 
      from tblNEWB in ((checkCondition==false) ? joinedTblB.DefaultIfEmpty() : joinedTblB) 
      select new { 
       tblA.ValueA, 
       tblNEWB.ValueB 
      }); 

我希望这会工作,但我得到一个错误,说:“InvalidOperationException:'tblB'的成员访问'System.String ValueB'不合法的类型'System.Collections.Generic.IEnumerable'1 [tblB]”

我在这里错过了什么吗?

UPDATE

我要的是一个外连接,但LINQ没有产生我希望,在条件上设置天龙八部查询。打开SQL事件探查器给出了这样的查询:

LEFT OUTER JOIN tblB ON tblA.Ref = tblB.REfA AND tlbB.Key = '100' 

虽然正确的查询应该是:

LEFT OUTER JOIN tblB ON tblA.Ref = tblB.RefA 
WHERE tblB.Key = '100' 

这样做的原因是我GetMyTable功能,设置条件表中加入。

+1

我不明白你想要做什么,但知道这一点:tblB超出范围后进入声明。然后,您将为具有相同名称的joinedTblB引入另一个范围变量。 –

+0

为什么不做两个单独的查询并将它们结合在一起? – R0MANARMY

+1

当您使用关键字时,它也不是内连接。解释清楚你想做什么,我们可以提供帮助。 –

回答

1

我想是这样的组合是什么相同的查询,并通过检查一些条件做一个外部连接或一个内部连接

获得您要求的第一步是识别需要两个不同的sql语句。 LinqToSql不会将您的条件发送到数据库中,因此数据库可以根据值确定应该发生什么样的连接。

第二步,是切换到方法语法。这种语法更符合条件。

第三步,就是放弃匿名类型。你必须做一些不愉快的事情来宣布你所需要的变量来与那些正在运行的查询构建。只需使用您需要的属性创建一个类型并使用它。

public class AandB 
{ 
    public A TheA {get;set;} 
    public B TheB {get;set;} 
} 

IQueryable<A> queryA = dc.TblA.AsQueryable(); 

IQueryable<AandB> queryAandB = null; 

if (checkCondition) 
{ 
    //inner join 
    queryAandB = queryA 
    .Join(
     GetMyTable(), 
     a => a.Ref, b => b.RefA, 
     (a, b) => new AandB() {TheA = a, TheB = b} 
    ); 
} 
else 
{ 
    // left join 
    queryAandB = queryA 
    .GroupJoin(
     GetMyTable(), 
     a => a.Ref, b => b.RefA, 
     (a, g) => new {a, g} 
    ) 
    .SelectMany(
     x => x.g.DefaultIfEmpty(), 
     (x, b) => new AandB(){TheA = x.a, TheB = b} 
    ); 
} 

List<AandB> results = queryAandB.ToList(); 
+0

我希望Linq能为我做“工作”。 感谢您的信息,我可能会用这个解决方案。 – hightow

0

如果不加入是你需要你的第一个查询应该做的工作

 (from tblA in dc.tblA 
     join tblB in GetMyTable() on tblA.Ref equals tblB.RefA into joinedTblB 
     from tblB in joinedTblB.DefaultIfEmpty() 
     select new {tblAField = tblA.F1 , tblBField = tblB == null ? null : tblB.F2); 

内部联接查询应该是这样的

 (from tblA in dc.tblA 
     join tblB in GetMyTable() on tblA.Ref equals tblB.RefA 
     select new { A = tblA, B = tblB }); 
0

我不确定这是否完全符合您的要求,但应该接近。

var query = from rowA in db.tblA 
      join rowB in db.tblB on rowA.idB equals rowB.idB into b 
      from item in b.DefaultIfEmpty() 
      select new 
      { 
       rowA.ValueA, 
       rowB.ValueB 
      };