Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/77.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql EntityFrameworkV6.1高效地加载深度相关的实体,然后查询它们_Sql_Entity Framework_Linq To Entities_Entity Framework 6 - Fatal编程技术网

Sql EntityFrameworkV6.1高效地加载深度相关的实体,然后查询它们

Sql EntityFrameworkV6.1高效地加载深度相关的实体,然后查询它们,sql,entity-framework,linq-to-entities,entity-framework-6,Sql,Entity Framework,Linq To Entities,Entity Framework 6,我有以下实体。类别、主题、帖子、成员。它们之间有以下联系: 类别有一个主题列表 Topic有一个帖子列表 该职位有一名成员 下面是课程 public class Category { public Guid Id { get; set; } public string Name { get; set; } public string Description { get; set; } public virtual IList<Topic> Topi

我有以下实体。类别、主题、帖子、成员。它们之间有以下联系:

  • 类别有一个主题列表
  • Topic有一个帖子列表
  • 该职位有一名成员
下面是课程

public class Category
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public virtual IList<Topic> Topics { get; set; }
}

public class Topic
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public DateTime CreateDate { get; set; }
    public virtual Category Category { get; set; }
    public virtual IList<Post> Posts { get; set; }
    public virtual MembershipUser User { get; set; }
}

public class Post
{
    public Guid Id { get; set; }
    public string PostContent { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateEdited { get; set; }
    public virtual Topic Topic { get; set; }
    public virtual MembershipUser User { get; set; }
}

public class MembershipUser
{
    public Guid Id { get; set; }
    public string UserName { get; set; }

    etc....

}
问题2
非常感谢您的帮助或指点。

如果您希望获得高效的性能,您可能有兴趣编写一个非常简单的MARS存储过程,其中包含您想要的所有数据。可以对每个结果集使用Translate函数来具体化模型对象。实体框架将自动修复您的导航属性

如果您不想创建一个proc,那么执行多个简单查询通常会更有效。我经常使用内存中的Id列表过滤LINQtoEntities查询,如:qry.where(x=>list.contains(x.Id))

自2014年9月21日起编辑

大多数开发人员认为高效的查询执行速度快,只返回所需的数据。这几乎是真的。然而,高效的数据访问层是重用有限数量的快速执行查询的层。有时,开发人员会以自己的方式尝试使每个查询尽可能高效,但没有意识到这会导致sql server管理太多的执行计划并降低总体性能。对于给定的表,我建议您尝试使用两种或三种方法。我将从一个查询开始,该查询返回一个包含相关数据的主题,以及一个包含此场景所需数据的主题列表

以下方法将在DataContext类中使用:

public Topic GetTopic(int topicId) 
{
      return this.Topics.Include("Posts.User").Single(x => x.Id = topicId);
}
这可以放在你的主题课上:

public Post GetMostRecentPost()
{
    return this.Posts.OrderByDescending(x => x.DateCreated).FirstOrDefault();
}
或者,如果你真的只想得到最新的帖子,而从来没有发现自己需要查询所有帖子的主题,那么你可以在上下文中使用以下查询

public Post GetMostRecentPost(int topicId)
{
  return this.Posts.Include(x => x.Topic).Include(x=>x.User).where(x => x.TopicId == topicId).OrderByDescending(x => x.DateCreated).FirstOrDefault();
}

一般的经验法则是,如果您试图返回一篇文章,最好从context.Post开始查询,并尝试以此为基础构建查询。尽量避免使用select或selectmany等投影查询,除非您打算返回匿名对象,并且愿意执行sql分析以确保查询符合预期。

首先,您应该从测量当前查询时间开始。考虑到FirstOrDefault(),我希望这个查询运行得非常快

我通常使用Sql事件探查器来处理这类事情。在web应用程序中,我通常还使用StackExchange.MiniProfiler或Spiew。两者都可以连接到EF中,以提供精确的查询时间

Include的问题是EF在连接数据方面非常糟糕,因为它们使用它们连接数据,而不是加载多个集合。我写了一篇文章,包括数字和可能的解决办法

但总结一下我的发现,加入策略的糟糕程度取决于数据的形状。如果将表A中的一行与表B中的一行联接起来,就像这里的例子一样,,就没有问题了。当加载的实体很少或其中一个非常小时,也几乎看不到

在您的例子中,由于您只寻找最上面的帖子,所以我要考虑的唯一优化是投影数据,这样您就不会加载可能不需要的属性。但最有可能的是,你所做的任何事情都只需要几微秒

不过,我从一次twitter对话中知道,这是一个只读场景。这使得向查询中添加AsNoTracking()成为可能,从而减少dbcontext的工作(这是对应用服务器上cpu和内存的改进,而不是数据库)

所以,测量它。我希望它在x.Posts中运行,并将其更改为.Include(post=>post.User),这样您就可以只加载帖子和用户,而不加载类别和主题。它仍将连接这些节点,但不加载数据

UPDATE2:如何改为编写Query1的示例。我不确定是否存在差异,但我预计这可能会减少加载的数据。您必须查看探查器


_上下文.类别
.AsNoTracking()
.其中(x=>x.Id==类别Id)
.SelectMany(x=>x.Topics)
.SelectMany(x=>x.Posts)
.Include(x=>x.User)
.OrderByDescending(x=>x.DateCreated)
.FirstOrDefault();

如果查询按照我的预期运行,那么这应该非常接近最佳查询。正如我所说。您需要检查生成的查询才能真正了解。

谢谢您的评论。我试图避免使用存储过程。此外,我还尝试对ID使用contains()执行多个简单查询,但查询速度似乎较慢?再次查看您的查询,我意识到您需要一个非常简单的查询。三张桌子不多。尝试以下方法:context.Topics.Include(“Posts.User”).Single(x=>x.Id=topicId)、selectmany(x=>x.Posts)、orderbydescending(x=>x.DateCreated)、FirstOrDefault()。要记住的重要一点是尽可能保持查询的简单性,并在检索数据后在内存中进行投影。如果上面的查询不起作用,请让我知道。谢谢你的例子。这几乎就是我上面所说的。尽管include在Single()查询之前。我认为它应该是在之后,以使它更有效(见官方文件链接)?-还有,为什么要使用Single()而不是FirstOrDefault()?谢谢米凯尔,谢谢你的评论。查询1呢?在你的博客文章中,你只涉及一个级别的包含。但如果我是说,试着做一个你的建议,加载所有集合并将它们合并到内存中。。。这是您的方法吗?在加载单个实体时,您真的不需要经历所有这些麻烦。无论如何,这将非常快。检查新的更新,了解我将如何编写Q1
public Post GetMostRecentPost()
{
    return this.Posts.OrderByDescending(x => x.DateCreated).FirstOrDefault();
}
public Post GetMostRecentPost(int topicId)
{
  return this.Posts.Include(x => x.Topic).Include(x=>x.User).where(x => x.TopicId == topicId).OrderByDescending(x => x.DateCreated).FirstOrDefault();
}