从一方面来说,我想编写一个杀手级应用程序(在ASP.NET MVC中);) 但另一方面,如果我不惜一切代价坚持所谓的“最佳实践”,我有很多疑问。所以我有一个设计问题,我真的希望你能帮助我。
想象一下标准博客。我想展示10个最近的帖子。我的数据库有标准
Posts, Categories, Tags, PostTags
表。因此,作为一个自然结果,我的域Post类具有如下属性:
public Category Category { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
我使用EF4和POCO支持。我用标准查询加载数据:
from p in context.Posts.Include("Category").Include("Tags")
select p
但是为什么我要加载整个Post类(例如那些2个属性),当我在页面上显示的所有内容(除了帖子本身)都是类别和每个标签的链接,所以我需要的所有列分别是:
[Categories].[Name], [Categories].[Slug], [Tags].[Name], [Tags.Slug]
。
我不需要整个Category或Tag实例(数据库中相应表中可能有100列)!我想,当一个网站收到很多请求时,它就很重要了。所以不加载所有列(避免可怕的SELECT *
)。
我以为我可以在我的域中添加一个新类,比如:ShortPost。但我觉得这不是我的领域! Post是模型,ShortPost是......好吧,只是完整帖子的一部分。此外 - 这个ShortPost对我来说就像是为了取悦视图而调整/调整域名(模型)。
总结一下:我应该在View端加载整个Model实例吗?我不需要整个对象吗?你能告诉我一些首选的解决方案/方法/等吗?
答案 0 :(得分:2)
如何不使用您的实体阅读? 这是Command-Query Separation模式的一个特征。
如果您的查看所需的唯一字段是[类别]。[名称],[类别]。[Slug],[标签]。[名称],[Tags.Slug]
然后创建一个代表此的DTO,并通过投射您的实体或直接查询您的数据存储来填充它。
public class PostDto
{
public string CategoryName { get; set; }
public string CategorySlug { get; set; }
public string TagName { get; set; }
public string TagSlug { get; set; }
}
答案 1 :(得分:1)
加载完整的域模型 - 这样就可以缓存它们,并在缓存中拥有完整的对象。
在缓存中部分填充对象会很困惑。
答案 2 :(得分:0)
鉴于你的例子 - 我会选择:
public class Post
{
public Category Category {get;set;}
}
public class Tag
{
public Post {get;set;}
}
这样就可以更轻松地查询您需要的时间给定的Post 所需的标签(您可以查询匹配Post的标签而不是查询Post标签 - 这样给出你有兴趣翻页,过滤等等。)
尽我所能,我倾向于避免集合(除非它是没有父对象时不能存在的值对象)。根据我的经验,维护起来要容易得多。
如果您在某个时候需要显示关于您的帖子的统计信息(它附加了多少个标签等) - 您可以使用您需要的数据来使用数据的“视图”(相当于表中的视图)你的数据库)。视图不在您的域中 - 因此您无需遵守域规则。然后,当您进入“编辑模式”时,您将加载完整的实体。