LINQ 中的条件加入

发布于 2024-12-09 17:46:16 字数 1477 浏览 0 评论 0原文

所以我在 linq 方面遇到了一些问题。我希望连接是 OUTER JOIN 或 INNER JOIN,具体取决于是否在表

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:成员访问 'System.String ValueB' of 'tblB' 在类型 'System.Collections.Generic.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 函数为联接中的表设置了条件。

So I'm having a little problem with linq. I want a join to be an OUTER JOIN or an INNER JOIN, depending on whether or not values are filtered on the table

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

What I want is to combine this in the same query, and by checking some condition do either an OUTER JOIN or an INNER JOIN, something like this:

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

I was hoping this would work, but I get an error saying "InvalidOperationException: Member access 'System.String ValueB' of 'tblB' not legal on type 'System.Collections.Generic.IEnumerable'1 [tblB]"

Am I missing something here?

UPDATE:

What I want is an outer join, but linq did not produce the query I hoped for, when conditions are set on tlbB. Turning on SQL Profiler gives this query:

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

While the correct query should be:

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

The reason for this is my GetMyTable-function that sets condition to the table in the join.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

感性 2024-12-16 17:46:16

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

What I want is to combine this in the same query, and by checking some condition do either an OUTER JOIN or an INNER JOIN

The first step to getting what you are asking for is to recognize that two distinct sql statements are required. LinqToSql is not going to send your condition into the database so the database can figure out what kind of join should happen based on a value.

The second step, is to switch to the method syntax. This syntax is more composable by conditions.

The third step, is to abandon anonymous types. You have to do unpleasant things to declare the variables you need for query construction with those running around. Just create a type with the properties you need and use that.

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();
蓝眸 2024-12-16 17:46:16

如果左连接是您所需要的,您的第一个查询应该完成工作,

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

if left join is what you need your first query should do the job

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

inner join query would look like this

        (from tblA in dc.tblA
         join tblB in GetMyTable() on tblA.Ref equals tblB.RefA 
         select new { A = tblA, B = tblB } );
穿越时光隧道 2024-12-16 17:46:16

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

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

I'm not sure if this does exactly what you're looking for, but it should be close.

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
            };
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文