3

我正在使用这个技巧来使用 EF 执行条件包含。http://blogs.msdn.com/b/alexj/archive/2009/10/13/tip-37-how-to-do-a-conditional-include.aspx

我遇到的问题是任何没有记录的集合都是空的,而不是空的。这引起了头疼,因为我必须先检查每个集合,然后才能在我的 mvc 视图中遍历它,否则我会得到一个空引用异常。

例如,StudentModules 集合将为空。如何在我的查询中将其变成一个空列表?即无需遍历所有内容并进行检查。

我可以在 poco 中放置一个构造函数来初始化列表,从而修复它,但是 this 集合是 poco 中的虚拟成员(基于 EF 视频!) - 这肯定不是要走的路吗?

var query = from module in db.Modules
            where module.Id == id
            select new 
            {
              module,
              QualificationModules = from qualificationModule in module.QualificationModules
                                     where qualificationModule.IsDeleted == false
                                     select new
                                     {
                                       qualificationModule,
                                       qualificationModule.Qualification,
                                       StudentModules = from studentModule in qualificationModule.StudentModules
                                                        where studentModule.IsDeleted == false 
                                                        select new
                                                        {
                                                          studentModule,
                                                          studentModule.Student
                                                        }
                                     },

              Assessments = (from assessment in module.Assessments
                             where assessment.IsDeleted == false
                             select new
                             {
                               assessment,
                               assessment.AssessmentType
                             }
                            )
            };

var modules = query.AsEnumerable().Select(x => x.module);

return modules.ToList().First();
4

1 回答 1

2

关系修复在实体附加到上下文时运行 - 通过调用手动Attach或当实体作为查询的结果实现时(您的情况)。

它基于实体的外键并双向工作:

  • 如果上下文已经包含一个具有实体A外键f的实体B,并且一个实体B被附加到具有与f外键相同值的主键的上下文A(即两个实体通过 FK 关系相关),则 Entity框架将执行以下操作:

    • 如果A有一个导航引用属性,B它将把附加的实体分配B给这个属性。
    • 如果B有一个导航引用属性A(一对一的关系),它将分配A给这个属性。
    • 如果B具有导航集合属性A(一对多关系),它将添加A到附加实体中的此集合中B。如果集合是null,它将在添加之前实例化集合。
  • 如果一个实体B被附加到上下文中,该上下文具有上下文已经包含f的实体的外键A,并且具有f作为主键的实体 EF 将根据与上述相同的规则设置导航属性。

附带说明:关系修复基于外键的事实(它们总是在您查询实体时加载,无论 FK 是否作为模型类中的属性公开)也是关系修复的原因不适用于多对多关系,也不适用于多对多关系,因为多对多关系的两个实体没有外键。

现在,如果StudentModules在您的情况下没有相关内容,则没有StudentModule实体被加载到上下文中,并且 EF 没有任何东西可以作为修复的目标。请记住,修复算法与特定查询无关,并且不仅修复了该查询将实现的实体之间的关系,而且它会考虑上下文已经包含的所有实体进行修复,无论它们如何进入上下文。如果您希望集合被实例化为空集合,EF 已经运行了所有附加的父实体StudentModules并创建一个空集合。在修复期间执行此操作而不是在实体附加到上下文之前预先创建空集合是没有意义的。

我可以在 poco 中放置一个构造函数来初始化列表,从而修复它,但是 this 集合是 poco 中的虚拟成员(基于 EF 视频!) - 这肯定不是要走的路吗?

在我看来,如果您不想在模型类实例中包含集合,这是最好的解决方案。null是否将集合声明为virtual(以启用延迟加载)并不重要。集合类型没有派生代理类型,只有添加到集合中的实例是派生代理。在这两种情况下,您都可以使用StudentModules = new HashSet<StudentModule>();(或者List如果您愿意)。

于 2013-05-15T16:27:01.700 回答