考虑博客数据模型:
Blog:
int Id
ICollection<Post> Posts
Post:
int Id
int BlogId
DateTime Date
然后加载具有最新帖子日期的Blogs(LatestPostDate)并绑定到UI,同时按上下文跟踪它们。
有一些解决方案,例如使用DTO,但上下文不会跟踪结果实体 。 此外,我可以将LatestPostDate设置为NotMapped,定义一个表值函数,并在DbSet上应用SqlQuery。虽然NotMapped字段没有以这种方式加载。
最佳做法是什么?
我尽量不向表中添加列,也避免在加载后计算值。
答案 0 :(得分:0)
最佳做法是处理ViewModel中的显示问题。
但是由于您不想将实体映射到另一个类,让我们首先看看[NotMapped]
变体,使用LINQ来计算最新的发布日期而不是纯SQL。
using System.Linq;
public class Blog {
public int Id { get; set; }
public virtual ICollection<Post> Posts { get; set; }
[NotMapped]
public DateTime? LatestPostDate {
get {
return Posts.OrderBy(p => p.Date).LastOrDefault()?.Date;
}
}
}
这样,只有在访问属性LatestPostDate
时(可能在UI渲染期间)才会计算该值。您可以eager loading Posts
减少数据库访问次数,但这会增加您正在使用的数据集的大小。
var blogs = _dbContext.Blogs.Include(b => b.Posts).ToArray();
但是如果你使用ViewModel,你可以一次填充LatestPostDate
:
public class BlogViewModel {
public int Id { get; set; }
public DateTime? LatestPostDate { get; set; }
}
var viewModels = _dbContext.Blogs.Select(b => new BlogViewModel {
Id = b.Id,
LatestPostDate = b.Posts.OrderBy(p => p.Date).LastOrDefault()?.Date;
}).ToArray();
关于上下文不跟踪ViewModel的问题:在编辑用例中,使用ViewModel提供的Id再次加载Entity并映射更新的属性。这使您可以完全控制应该可编辑的属性。作为奖励,ViewModel是进行输入验证,格式化等的好地方。