LINQ中的条件连接

本文关键字:连接 条件 LINQ | 更新日期: 2023-09-27 18:11:28

所以我有一个小问题与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);

内连接:

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:成员访问"系统。在类型"System.Collections.Generic"上,"tblB"的字符串值不合法。IEnumerable 1 (tblB)"

我错过了什么吗?

:

我想要的是一个外部连接,但是当在tlbB上设置条件时,linq没有产生我希望的查询。打开SQL Profiler会得到如下查询:

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-function设置了连接表的条件

LINQ中的条件连接

我想要的是将它们组合在同一个查询中,并通过检查某些条件来执行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();

如果左连接是你需要的,你的第一个查询应该做的工作

        (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 } );

我不确定这是否正是你正在寻找的,但它应该接近。

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
            };