假设我有一个User
实体,并创建了部分User
类,因此我可以添加一些方法(例如NHibernate)。我添加了GetByID
以使用户更容易:
public static User GetByID(int userID)
{
using (var context = new MyEntities())
{
return context.Users.Where(qq => qq.UserID == userID).Single();
}
}
现在,在业务逻辑中的某处我想做这样的事情:
var user = User.GetByID(userID);
var posts = user.GetAllPostsForThisMonth();
foreach(var post in posts)
{
Console.WriteLine(post.Answers.Count);
}
GetAllPostsForThisMonth()
与GetByID
相似-具有上下文,并在执行后立即将其处置。通常我无法执行此操作,因为调用
post.Answers.Count
时会处理上下文。我认为这使我的方法无用...还是我错过了什么?我可以这样使用我的实体吗?还是应该为我使用的每个查询创建方法(例如post.GetAnswersCount()
)?提前致谢! 最佳答案
您所哀叹的行为实际上是好的,因为它使您无法射击自己的脚。如果允许您执行此操作,则会导致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();
}
}
这将产生一个SQL查询,并且在一次往返过程中将准确产生您想要的信息,而不会加载大量您不想要的信息。
更新资料
如果NHibernate可以像Java的Hibernate一样工作,那么在处理完上下文后,它也不会进行延迟加载。实体框架确实为您提供了许多选择,具体取决于您的具体情况。例如:
可以使上下文的持续时间更长(例如,在Web应用程序中每个请求一次),而不是将上下文范围限制在数据访问方法之内,以便使属性的延迟加载将继续在数据访问方法之外进行。
您可以热切地加载所需的任何实体关联。
这是一个渴望加载的例子:
public GetAllPostsAndAnswersForThisMonth()
{
using (var context = new MyEntities())
{
return context.Posts.Include("Answers")
.Where(p => p.UserID == UserID)
.ToList();
}
}
但是,由于Entity Framework本质上构成了您的“数据访问”层,因此我仍然认为,最佳实践是创建一个或一组类来准确地建模您的业务层实际想要从数据层中获取的内容,然后数据访问方法产生这些类型的对象。
关于c# - 我可以使用没有上下文的实体吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6600807/