将Include()与继承的实体一起使用

时间:2010-02-23 11:03:58

标签: entity-framework inheritance join eager-loading

在EF eager中,相关实体是easy

但是在使用每个类型的表模型加载数据时,我遇到了包括继承实体的困难。

这是我的模特:

实体

  • ArticleBase(基础文章实体)
    • ArticleSpecial(继承自ArticleBase
  • UserBase(基本用户实体)
    • UserSpecial(继承自UserBase
  • Image

关系如图所示(省略多列): alt text http://i48.tinypic.com/5x4kdc.jpg

实际上,我的用户始终是UserSpecial类型,因为UserBase用于另一个应用程序,因此我们可以共享凭据。这是我有两个单独的表的唯一原因。 UserBase表格不能以任何形式或形式进行更改,因为其他应用程序会中断。

问题

我如何设置同时设置ArticleSpecialCreatedBy的{​​{1}},以便两者都是EditedBy类型(定义{{​​1}}关系)?


我尝试了这些选项(但未成功):

1。 使用lambda表达式:

UserSpecial

在这种情况下,问题是Imagecontext.ArticleBases .OfType<ArticleSpecial>() .Include("UserCreated.Image") .Include("UserEdited.Image"); 都与CreatedBy相关,但未定义EditedBy导航。所以我应该以某种方式将这两个类型转换为UserBase类型:

Image

但当然在UserSpecial中使用泛型不起作用。

2。 我尝试过使用LINQ查询

context.ArticleBases
    .OfType<ArticleSpecial>()
    .Include("UserCreated<UserSpecial>.Image")
    .Include("UserEdited<UserSpecial>.Image");

在这种情况下,我只获得Include("UserCreated<UserSpecial>.Image")个对象实例而没有设置相关属性。我知道我应该以某种方式选择那些,但我不知道怎么做?

我的LINQ中的选择部分可以更改为

var results = from articleSpecial in ctx.ArticleBase.OfType<ArticleSpecial>()
                  join created in ctx.UserBase.OfType<UserSpecial>().Include("Image")
                  on articleSpecial.UserCreated.Id equals created.Id
                  join edited in ctx.UserBase.OfType<UserSpecial>().Include("Image")
                  on articleSpecial.UserEdited.Id equals edited.Id   
              select articleSpecial;

但图片仍未加载到我的上下文中。我在这种情况下的联接几乎不用于过滤articleSpecial结果,但它们不会将实体加载到上下文中(我想)。

1 个答案:

答案 0 :(得分:3)

这似乎是当前版本的Entity Framework(1.0)中的限制请查看this related SO question

在您的情况下,在投影中包含相关的 UserCreated UserEdited 属性是正确的解决方案。但是,如果您还想在 UserSpecial 对象上填充图像属性,则必须确保包含该属性:

var results = from articleSpecial in ctx.ArticleBase.OfType<ArticleSpecial>()
              select new
              {
                  articleSpecial,
                  articleSpecial.UserCreated,
                  ((UserSpecial)articleSpecial.UserCreated).Image,
                  articleSpecial.UserEdited,
                  ((UserSpecial)articleSpecial.UserEdited).Image
              };

当然,此查询建立在所有ArticleSpecial实体始终引用UserSpecial实体的假设之上,否则转换将失败。
如果这个假设并不总是正确,你可以使用LINQ扩展方法和多行lambda函数来表达相同的查询来执行安全的转换:

var results = ctx.ArticleBase
                 .OfType<ArticleSpecial>()
                 .AsEnumerable()
                 .Select(a =>
                  {
                      var userCreated = a.UserCreated as UserSpecial;

                      if (userCreated != null)
                      {
                          var image = userCreated.Image;
                      }

                      var userEdited = a.UserEdited as UserSpecial;

                      if (userEdited != null)
                      {
                          var image = userEdited.Image;
                      }

                      return a;
                  });

在后一个示例中,您还不需要在结果中包含 UserSpecial 图像实体。相反,您只需在投影阶段访问 ArticleSpecial 实体上的导航属性,以强制Entity Framework急切加载相关对象。