【问题标题】:Linq left outer join not working using DefaultIfEmptyLinq 左外连接无法使用 DefaultIfEmpty
【发布时间】:2013-02-04 14:30:23
【问题描述】:

使用 MSDN 文章 "How to: Perform Left Outer Joins (C# Programming Guide)" 中的技术,我尝试在我的 Linq 代码中创建左外连接。文章提到使用DefaultIfEmpty 方法从组连接创建左外连接。基本上,它指示程序包含左(第一个)集合的结果,即使右集合中没有结果。

然而,这个程序的执行方式,就好像没有指定外连接一样。

在我们的数据库中,AgentProductTraining 是我们的代理所学课程的集合。通常,如果不将相应的值输入到CourseMaterials 表中,您就无法将Course 输入到相应的表中。但是,有时这种情况可能会发生,因此我们希望确保即使在 AgentProductTraining 中列出了 Course 而在 CourseMaterials 中没有任何相应信息时,我们也会返回结果。

var training = from a in db.AgentProductTraining
    join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm
    where
        a.SymNumber == id 
        from m in apm.DefaultIfEmpty()
        where m.EffectiveDate <= a.DateTaken
        && ((m.TerminationDate > a.DateTaken) | (m.TerminationDate == null))
            select new
            {
                a.AgentProdTrainId,
                a.CourseCode,
                a.Course.CourseDescription,
                a.Course.Partner,
                a.DateTaken,
                a.DateExpired,
                a.LastChangeOperator,
                a.LastChangeDate,
                a.ProductCode,
                a.Product.ProductDescription,
                m.MaterialId,
                m.Description,
                a.Method
            };

【问题讨论】:

  • 是否有导航属性AgentProductTraining.CourseMaterials
  • 另外,标题说left inner join not working,但我认为它是outer join?实际上,您的帖子中并没有真正的问题陈述。
  • 很好,谢谢。我不相信我们在 CourseMaterials 上有导航属性

标签: asp.net-mvc asp.net-mvc-3 linq entity-framework-4


【解决方案1】:

MSDN 示例使用了一个新变量subpet

var query = from person in people
                    join pet in pets on person equals pet.Owner into gj
                    from subpet in gj.DefaultIfEmpty()
                    select new { person.FirstName, PetName = (subpet == null ? String.Empty : subpet.Name) };

所以你必须使用你自己的“子宠物”,我使用submat 变量重写了你的代码:

        var training = from a in db.AgentProductTraining
                       join m in db.CourseMaterials on a.CourseCode equals m.CourseCode into apm
                       where
                           a.SymNumber == id
                           from submat in apm.DefaultIfEmpty()
                           where 
                           (submat.EffectiveDate <= a.DateTaken || submat.EffectiveDate == null) &&
                           (submat.TerminationDate > a.DateTaken || submat.TerminationDate == null)
                       select new
                                  {
                                      a.AgentProdTrainId,
                                      a.CourseCode,
                                      a.Course.CourseDescription,
                                      a.Course.Partner,
                                      a.DateTaken,
                                      a.DateExpired,
                                      a.LastChangeOperator,
                                      a.LastChangeDate,
                                      a.ProductCode,
                                      a.Product.ProductDescription,
                                      MaterialId = (submat==null?-1:submat.MaterialId),
                                      Description = (submat==null?String.Empty:submat.Description),
                                      a.Method
                                  };

【讨论】:

  • 由于某种原因,我在training 变量的Results View 部分收到以下错误消息(不知道为什么,目前正在调查)The cast to value type 'Int32' failed because the materialized value is null. Either the result type's generic parameter or the query must use a nullable type.
  • 我认为submat.MaterialId 不能为空,因此在外部连接返回空的情况下(当 AgentProductTraining 记录没有 CourseMaterials 时),您必须设置默认值。在这种情况下,我将编辑代码以设置 -1。
  • 对不起... VS2010 不喜欢那样。我收到消息Invalid anonymous type member declarator. Anonymous type members must be declaure with a member assignment, simple name or member access
  • 哦,意思是你必须为那两个成员指定一个名字,让我编辑答案。
  • @NealR 很高兴!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-10
  • 1970-01-01
  • 1970-01-01
  • 2019-11-08
相关资源
最近更新 更多