【问题标题】:Entity framework. Quering parent entity with subclass property loaded实体框架。查询加载了子类属性的父实体
【发布时间】:2012-10-11 11:30:03
【问题描述】:

有一个简单的域..

public abstract class UserComment
{
    public string Text { get; set; }
}

public class BlogComment : UserComment
{
    public Blog Blog { get; set; }
}

public class PhotoComment : UserComment
{
    public Photo Photo { get; set; }
}

有没有办法查询所有类型为 UserComment 的实体并加载了属性博客和照片?

var comment = DbContext.Set<UserComment>()
    .Include(x => x.Blog) // will not compile
    .Include(x => x.Photo) // will not compile
    .FirstOrDefault();

if (comment is PhotoComment )
{
    string url = (comment as PhotoComment).Photo.Url;
}
if (comment is BlogComment)
{
    var dateCreated = (comment as BlogComment).Blog.DateCreated;
}

谢谢!

【问题讨论】:

  • 如果您的问题提供了有用的信息(更不用说点赞),您应该接受(标记为已接受)。这是对回答您问题的人的奖励。
  • 这个链接在哪里?我看不到任何名为“接受答案”的按钮或链接。
  • 我认为it's here
  • 好的,现在,我想这不是代码优先?你试过comment.Blog.Load()explanation
  • 我先使用代码。你提到的,我查看了加载扩展。并找到了可能的解决方案 - 将父类转换为子类并使用加载扩展:context.Entry(comment as BlogComment).Reference(p =&gt; p.Blog).Load();

标签: c# entity-framework linq-to-entities ef-code-first


【解决方案1】:

您可能需要两次查询才能获得结果。如果您只想要第一个元素 (FirstOrDefault) 显式加载 - 正如您在 cmets 中已经提出的那样 - 是一个好方法:

var comment = DbContext.Set<UserComment>().FirstOrDefault();

if (comment is BlogComment)
    DbContext.Entry(comment as BlogComment).Reference(bc => bc.Blog).Load();
else if (comment is PhotoComment)
    DbContext.Entry(comment as PhotoComment).Reference(pc => pc.Photo).Load();

如果您想加载 UserComments 的列表,这不是最佳解决方案,因为它需要遍历加载的 UserComments 并为每个元素调用显式加载,这将导致许多查询。

对于列表,您可以使用以下方法,该方法也只会生成两个查询:

IEnumerable<UserComment> blogComments = DbContext.Set<UserComment>()
    .OfType<BlogComment>()
    .Include(bc => bc.Blog)
    .Cast<UserComment>()
    .AsEnumerable();

IEnumerable<UserComment> photoComments = DbContext.Set<UserComment>()
    .OfType<PhotoComment>()
    .Include(pc => pc.Photo)
    .Cast<UserComment>()
    .AsEnumerable();

List<UserComment> comments = blogComments.Concat(photoComments).ToList();

由于使用了AsEnumerable(),这将运行两个单独的数据库查询并将结果连接到内存中的单个集合中。

LINQ-to-Entities 支持Cast,但由于某种原因,无法删除两个AsEnumerable() 转换以仅获取单个数据库查询并将结果连接到数据库中。代码仍然可以编译,但我遇到了一个关于无效Include 路径的运行时异常。

我已经用 EF 4.1 进行了测试。可能值得用 EF 5.0 测试没有 AsEnumerable() 的查询,看看它是否仍然失败。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多