【问题标题】:LINQ Left Outer Join with Greater Than and Less Than Date Conditions具有大于和小于日期条件的 LINQ 左外连接
【发布时间】:2019-03-18 08:32:29
【问题描述】:

我已经为此苦苦挣扎了一段时间,找不到基于日期具有多个条件的 LINQ 外连接的语法。我一直在研究 GroupJoin 语法,但这只能让您比较一个字段值(通常是 ID)。

我想测试父表的日期(例如“UpdateDate”)是否属于子表中定义的多个值(例如“StartDate”和“EndDate”)。如果父日期符合条件,请从子表中拉出一两列。如果不是,则子表中的那些列应该为空(经典的左连接内容)。

我认为查询语法不会起作用,因为它只能识别等值连接。

有没有办法在 LINQ 中使用 Lambda 语法做到这一点?我一直在尝试使用“SelectMany”和“DefaultIfEmpty”的某种组合,但在尝试定义连接时一直卡住。

【问题讨论】:

  • 您能否添加一些示例数据(3 - 10 个实体)以及哪些实体应在某些给定的约束条件下出现?
  • 关于样本数据,为简单起见,想象一个具有 ID、Desc 和 UpdateDate 的父表和一个具有 StartDate、EndDate 和 WeekNumber 列的子表(也许“辅助”表会是更好的描述) .两个表之间没有匹配的列。我希望这会有所帮助...
  • 不。请在您的问题中添加一些代码。写下一个简单的示例类(例如public class MyEntity { public int Id {get; set;} } 或多个以显示关系)和一些代码,这些代码创建一个包含几个实体的列表(或多个用于关系)。然后写下您希望在查询中设置哪些约束以及上述哪些实体应该出现。如果你提供这个,我可以很容易地复制这段代码并解决你的问题。

标签: linq conditional left-join


【解决方案1】:

在 linq 中这样做的方法:

var q = from a in TableA
        from b in TableB.where(x => a.Date > x.StartDate && a.Date < x.EndDate).DefaultIfEmpty()
        select {...}

【讨论】:

  • 啊哈,是的,into g 在这种情况下没有用,因为它不是组加入。更新了答案。
【解决方案2】:

使用Queryable.GroupJoin的参数ResultSelector来选择你想要的:

var result = dbContext.Parents.GroupJoin(dbContext.Children,

    // outer and inner key Selectors:
    parent => parent.Id,       // from every parent take the primary key
    child => child.ParentId,   // from every child take the foreign key to parent

    // ResultSelector: take the parent and all his children to make one new object
    (parent, children) => new
    {
        // Select only the Parent properties you actually plan to use:
        Id = parent.Id,
        Name = parent.Name,
        ...

        Children = children.Select(child => new
        {
            // select only Child properties you plan to use:
            Id = child.Id,
            // No need: you know the value: ParentId = child.ParentId,
            ...

“如果父日期符合条件,则从子表中拉一两列,否则子表中的那些列应该为空”

            SpecialColumnA = (parent.BirthDay.Year < 2000) ?? child.BirthDay : null,
            SpecialColumnB = (parent.Name == "Kennedy" ?? child.Name : null,
    });

如果很多列的条件相同,请考虑只检查一次:

        SpecialColumns = (parent.Birthday.Year >= 2000) ? null :
            // else fill the special columns:
            new
            {
                Name = child.Name,
                SomeWeirdProperty = parent.Id + child.Id,
                ...
            },
    }); 

【讨论】:

  • Harold,两个表之间没有匹配的主键/外键列。我没有设计数据库....您的解决方案在这种情况下仍然适用吗?
  • GroupJoin 是 SQL Left Outer Join 后跟 GroupBy。如果您的键选择器选择可用于连接的属性,那么我想它可以工作。另一方面:为什么不在List&lt;Parent&gt;List&lt;Child&gt; 的虚拟项目中尝试呢?
  • 我一直在尝试一个虚拟项目,但无法让它工作,这就是我在这里发布的原因。
  • 有趣。我尝试了两个列表,我在其中 GroupJoined parents 和 Child on LastName,以获得“Parents with their children”。它奏效了。
猜你喜欢
  • 2012-01-08
  • 2010-11-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多