【问题标题】:Left join is not working for complex query左连接不适用于复杂查询
【发布时间】:2012-08-10 11:04:07
【问题描述】:

我有一个非常复杂的 linq 查询,它可以很好地用于内部连接,即没有 z_temp.DefaultIfEmpty()。但是当我将它用于左连接时,查询没有产生结果。

var q = from x in db.EmployeesList
        where x.EmployeesListStartDate >= startDate && x.EmployeesListStartDate <= endDate
        join y in db.Survey on x.Survey.SurveyID equals y.SurveyID
        join z in
                (from a in db.Commit
                 join b in
                         (from commit in db.Commit
                          where
                            commit.CommitListID != null &&
                            commit.CommitType.ToUpper() != "PREVIEW"
                          group commit by new
                          {
                              commit.CommitListID
                          } into g
                          select new
                          {
                              CommitListID = (Int32?)g.Key.CommitListID,
                              CommitId = (Int32?)g.Max(p => p.CommitId)
                          })
                       on new { a.CommitListID, a.CommitId }
                   equals new { b.CommitListID, CommitId = (Int32)b.CommitId }
                 select new
                 {
                     CommitListID = (Int32?)a.CommitListID,
                     CommitUsername= a.CommitUsername,
                     CommitStartDateTime=a.CommitStartDateTime,
                     CommitType=a.CommitType,
                     CommitSuccessCount=a.CommitSuccessCount
                 }) on new { EmployeesListID = x.EmployeesListID } equals new { EmployeesListID = (Int32)z.CommitListID }
                 into z_temp
        from _z in z_temp.DefaultIfEmpty()
        select new CustomEmployeesList
        {
            SurveyId = x.Survey.SurveyID != null ? (int)x.Survey.SurveyID : 0,
            EmployeesListId = x.EmployeesListID != null ? (int)x.EmployeesListID : 0,
            EmployeesListName = x.EmployeesListName,
            SpecificMessage = x.SpecificMessage,
            ListCriteria = x.ListCriteria,
            Channel = x.Channel,
            EmployeesListStartDate = (DateTime)x.EmployeesListStartDate,
            EmployeesListEndDate = (DateTime)x.EmployeesListEndDate,
            Records = x.Records != null ? (int)x.Records : 0,
            QueryId = x.AppSqlQueries.QueryId != null ? (int)x.AppSqlQueries.QueryId : 0,
            //AuditId = (Int32?)x.AuditEntry.AuditId,
            StatusCommonCode = x.CommonCode.CommonCodeId != null ? (int)x.CommonCode.CommonCodeId : 0,
            SurveyName = y.SurveyName,
            LastCommitDateTime = _z.CommitStartDateTime.HasValue ? (DateTime)_z.CommitStartDateTime : DateTime.MinValue,
            LastCommitType = _z.CommitType != null ? _z.CommitType : "",
            LastCommitUsername = _z.CommitUsername != null ? _z.CommitUsername : "",
            LastCommitCount = _z.CommitSuccessCount.HasValue ? (int)_z.CommitSuccessCount : 0
        };

这不返回任何结果,并且 我在调试模式下查看结果时收到此异常消息:

LINQ to Entities 无法识别该方法 'System.Collections.Generic.IEnumerable1[f_AnonymousType351[f_AnonymousType35%5bSystem.Nullable1[System.Int32],System.String,System.Nullable1%5bSystem.DateTime%5d,System .String,System.Nullable`1%5bSystem.Int32%5d%5d%5d">System.Nullable1[System.Int32],System.String,System.Nullable1[System.DateTime],System.String,System.Nullable1[ System.Int32]]] DefaultIfEmpty[f__AnonymousType35' 方法,并且该方法不能 翻译成商店表达式。

任何人都可以提出问题所在,这将非常有帮助!

【问题讨论】:

  • 错误似乎来自这一行:from _z in z_temp.DefaultIfEmpty()你想在那里做什么?
  • 是的,我想加入EmployeesList 表
  • 假设您的数据库很复杂,您应该使用 Entity Framework 和 linq to entity。我以前从未见过这样的东西..
  • 是的,我正在使用实体框架,这是 linq 到实体。这个查询是一个非常复杂的在两个表上使用 3 次连接的查询,但是查询正常执行成功,即内连接。但是当我想离开加入“EmployeesList”时,即在Linq中添加 - “into z_temp from _z in z_temp.DefaultIfEmpty()”,我得到了错误。我检查了所有空值并确保。但不知道为什么我没有得到结果?

标签: c# .net linq linq-to-sql left-join


【解决方案1】:

问题出在这一行:

 from _z in z_temp.DefaultIfEmpty()

如果没有行与联接匹配,则调用 DefaultIfEmpty() 将返回 null。好的,您是左连接,但您必须在访问其成员之前测试 _z 是否为 null

 ...
 LastCommitDateTime = _z == null ? DateTime.MinValue : (_z.CommitStartDateTime.HasValue ? (DateTime)_z.CommitStartDateTime : DateTime.MinValue),
 LastCommitType = _z == null ? "" : (_z.CommitType != null ? _z.CommitType : ""),
 ...
 etc.

更优雅的替代方法是创建一个定义所需字段的类并调用_z.DefaultIfEmpty(new ZRow()),这样您就无需在每次需要时测试_z 是否为空。但在这种情况下,您需要更改为z_temp 生成结果的select,并将其替换为select new ZRow(a.CommitListID, etc..)。没什么大不了的。

【讨论】:

  • 第一种检查 _z==null 的方法对于错误的可能原因是有意义的,当我执行时我得到了同样的错误。有趣的是,第二个给了我错误,LINQ to Entities 无法识别方法 'System.Collections.Generic.IEnumerable1[SA.Repository.CampaignManagement.CampaignManagementRepository+ZRow] DefaultIfEmpty[ZRow](System.Collections.Generic.IEnumerable1[SA.Repository.CampaignManagement.CampaignManagementRepository+ZRow], ZRow)' 方法,而这个方法不能翻译成存储表达式。我不知道该怎么办?
猜你喜欢
  • 1970-01-01
  • 2023-03-25
  • 2016-11-12
  • 2020-08-18
  • 2015-05-28
  • 1970-01-01
  • 2011-10-21
  • 2010-11-02
  • 1970-01-01
相关资源
最近更新 更多