【问题标题】:Performing 1-to-1 Left Outer Join in LINQ using Lambda expression使用 Lambda 表达式在 LINQ 中执行 1 对 1 左外连接
【发布时间】:2016-07-01 08:44:40
【问题描述】:

我有以下 LINQ 查询:

dbContext.NAVSummaries
        .Join(dbContext.NAVSummaries.DefaultIfEmpty(),
                current => new
                {
                    current.Portfolio,
                    PD = SqlFunctions.DatePart("dw", current.ValueDate) == 2 ? DbFunctions.AddDays(current.ValueDate, -3).Value :
                            SqlFunctions.DatePart("dw", current.ValueDate) == 1 ? DbFunctions.AddDays(current.ValueDate, -2).Value :
                                                                                DbFunctions.AddDays(current.ValueDate, -1).Value
                },
                previous => previous == null ? null : new { previous.Portfolio, PD = previous.ValueDate },
                (outer, inner) => new { outer, inner }
        )
        .Where(n => !dateStart.HasValue || n.outer.ValueDate.CompareTo(dateStart.Value) >= 0)
        .Where(n => !dateEnd.HasValue || n.outer.ValueDate.CompareTo(dateEnd.Value) <= 0)

给定的 ValueDate 有 x 条记录,在其上一个营业日期有 x-1 条记录。 NAVSummaries DbSet 在 ValueDate 列上自联接,其中 ValueDate 项匹配其先前的业务日期。但是,输出结果的计数仅为 x-1。我希望执行左外连接,以便返回左表/集合的所有 x 记录。

编辑:只有一条记录/项目与上一个营业日期匹配。所以它必须是一种一对一的映射。

NavSummary 实体:

public class NAVSummary
    {
        [Key, Column(Order = 0)]
        public string Portfolio { get; set; }
        [Key, Column(Order = 2)]
        public DateTime ValueDate { get; set; }
        public decimal BackOfficeNAV { get; set; }
        public decimal FrontOfficeNAV { get; set; }
        public decimal DifferencePercent { get; set; }
        public decimal Threshold { get; set; }
        public int ExtractId { get; set; }
        public string ExtractStatus { get; set; }
        public string PortfolioOwner { get; set; }
        public DateTime DateTimeModified { get; set; }
        public int MostCorrectNAV { get; set; }
        public virtual IList<NAVComment> Comments { get; set; }
        public virtual IList<NAVStatus> Statuses { get; set; }
        public virtual IList<NAVExtract> Extracts { get; set; }
        [JsonIgnore]
        [NotMapped]
        public bool IsChange { get; set; }
        [NotMapped]
        public decimal DayOverDayChange { get; set; }
        [JsonIgnore]
        [NotMapped]
        public DateTime PreviousValueDate { get; set; }
        [JsonIgnore]
        [NotMapped]
        public decimal PreviousDP { get; set; }
    }

【问题讨论】:

  • 你能展示一下课程吗?
  • @LucianBumb,添加了 NavSummary 实体类
  • 这有点令人困惑,为什么您要在实体内部尝试使用 LEFT JOIN,您能否展示您想要的查询结果?

标签: c# linq join lambda left-join


【解决方案1】:

在处理包括连接、分组等在内的复杂查询时,我建议您对大部分部分使用 LINQ 查询语法,因为透明标识符和let 表达式使它更加自然和可读。此处描述了不同类型的连接join clause (C# Reference)

这是您使用查询语法的查询:

var query =
    from current in db.NAVSummaries
    let currentWD = SqlFunctions.DatePart("dw", current.ValueDate)
    let currentPD = DbFunctions.AddDays(current.ValueDate, currentWD == 2 ? -3 : currentWD == 1 ? -2 : -1).Value
    join previous in db.NAVSummaries
    on new { current.Portfolio, PD = currentPD }
    equals new { previous.Portfolio, PD = previous.ValueDate }
    into previousGroup
    from previous in previousGroup.DefaultIfEmpty() // LEFT OUTER JOIN
    select new { outer = current, inner = previous };
if (dateStart.HasValue)
    query = query.Where(e => e.outer.ValueDate >= dateStart.Value);
if (dateEnd.HasValue)
    query = query.Where(e => e.outer.ValueDate <= dateEnd.Value);

【讨论】:

  • 感谢您为我重写查询。有效:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多