我可以使用没有上下文的实体吗

Epi*_*dex 2 c# entity-framework

假设我有一个User实体,并创建了部分User类,所以我可以添加一些方法(比如NHibernate).我添加GetByID了让用户更容易:

public static User GetByID(int userID)
{
    using (var context = new MyEntities())
    {
        return context.Users.Where(qq => qq.UserID == userID).Single();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,在业务逻辑的某个地方,我想做这样的事情:

var user = User.GetByID(userID);
var posts = user.GetAllPostsForThisMonth();
foreach(var post in posts)
{
    Console.WriteLine(post.Answers.Count);
}
Run Code Online (Sandbox Code Playgroud)

GetAllPostsForThisMonth()类似于GetByID- 具有上下文并在执行后立即处理它.

通常我不能这样做,因为我打电话时会处理上下文post.Answers.Count.我认为这会使我的方法变得无用......或者我错过了什么?我能不能这样使用我的实体?或者我应该为我使用的每个查询创建方法(比如post.GetAnswersCount())?提前致谢!

Str*_*ior 5

你感叹的行为实际上很好,因为它可以防止你在脚下射击.如果你被允许这样做,它将导致n往返数据库(n帖子的数量),并且每次往返都会拉出所有答案的所有数据,当你所有的想要的是Count.这可能会产生巨大的性能影响.

您要做的是构造一个对象,该对象表示您希望从数据库中获取所需的所有信息,然后构造一个LINQ查询,该查询将实际加载您希望使用的所有信息.

public class PostSummary
{
    public Post Post {get;set;}
    public int AnswerCount {get;set;}
}

public IEnumerable<PostSummary> GetPostSummariesByUserAndDateRange(
                                   int userId, DateTime start, DateTime end)
{
    using (var context = new MyEntities())
    {
        return context.Posts
               .Where(p => p.UserId == userId)
               .Where(p => p.TimeStamp < start && p.TimeStamp > end)
               .Select(new PostSummary{Post = p, AnswerCount = p.Answers.Count()})
               .ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

这会生成一个SQL查询,并且在一次往返中,可以生成您想要的信息,而无需加载大量您不想要的信息.

更新

如果NHibernate的工作方式与Java的Hibernate类似,那么在上下文处理后它也不会进行延迟加载.实体框架确实为您提供了许多选项:哪一个最适合您将取决于您的具体情况.例如:

  • 您可以使上下文的持续时间更长(比如Web应用程序中的每个请求一次),这样Lazy加载的属性将继续超出您的数据访问方法,而不是将您的上下文保留在数据访问方法中.
  • 您可以急切地加载您知道您将需要的任何实体关联.

这是一个急切加载的例子:

public GetAllPostsAndAnswersForThisMonth()
{
    using (var context = new MyEntities())
    {
        return context.Posts.Include("Answers")
                   .Where(p => p.UserID == UserID)
                   .ToList();
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,由于实体框架基本上构成了您的"数据访问"层,我仍然认为最佳实践是创建一个类或一组类,这些类可以准确地模拟业务层实际需要的数据层,然后具有数据访问方法生成这些类型的对象.