LINQ中的条件连接

时间:2011-10-14 12:50:28

标签: c# linq join

所以我对linq有点问题。我希望连接成为OUTER JOIN或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.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);

我想要的是在同一个查询中组合它,并通过检查某些条件做OUTER JOIN或INNER JOIN,如下所示:

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]上不合法”< / p>

我在这里错过了什么吗?

更新

我想要的是外连接,但是当在tlbB上设置条件时,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函数将条件设置为连接中的表。

3 个答案:

答案 0 :(得分:1)

  

我想要的是在同一个查询中组合它,并通过检查某些条件做OUTER JOIN或INNER JOIN

获得要求的第一步是要认识到需要两个不同的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();

答案 1 :(得分: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 } );

答案 2 :(得分: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
            };