我的团队使用 Entity Framework 开发了一个网络 API 应用程序, Gui 是由一个单独的团队开发的。
我的问题是应该如何定义模型?我们是否应该有两个项目 - 一个用于领域模型(数据库实体),另一个用于可序列化的 Dtos?
从 Dto 到域模型的解析应该在哪里发生,什么时候应该以相反的方式发生?
此外,有时需要将所有数据发送给客户端。是否也应该为这些情况创建一个 Dto?或者我应该返回一个域模型?
最佳答案
一般来说,最好不要让您的实体(数据库模型)泄露出您的数据库层。但是,与软件中的所有内容一样,这也有缺点。其中一个缺点是,它开始增加数据层的复杂性,因为它涉及将实体映射到数据库层中的 DTO,最终导致充满相似方法的存储库返回不同的 DTO 类型。
有些人还认为从数据层公开 IQueryables 也是一件坏事,因为您开始将抽象泄漏到不同的层 - 尽管这似乎总是有点极端。
就个人而言,我喜欢我认为更实用的方法,我更喜欢使用像 AutoMapper 这样的工具。自动将我的实体映射到业务逻辑层中的 DTO。
例如:
// Initial configuration loaded on start up of application and cached by AutoMapper
AutoMapper.Mapper.CreateMap<BlogPostEntity, BlogPostDto>();
// Usage
BlogPostDto blogPostDto = AutoMapper.Mapper.Map<BlogPostDto>(blogPostEntity);
AutoMapper 还可以配置更复杂的映射,但您应该尽量避免这种情况,坚持使用更扁平的 DTO。
此外,AutoMapper 的另一个重要功能是能够自动将您的实体投影到 DTO。这会导致更简洁的 SQL,其中仅查询 DTO 中的列:
public IEnumerable<BlogPostDto> GetRecentPosts()
{
IEnumerable<BlogPostDto> blogPosts = this.blogRepository.FindAll().Project(this.mappingEngine).To<BlogPostDto>().ToList();
return blogPosts;
}
Moreover, sometimes all the data is needed to be sent to the clients.. Should a Dto be created for those cases as well? Or should I return a domain model?
应该为这些创建 DTO。最终,您不希望您的客户端依赖于您的数据架构,这正是您公开实体时会发生的情况。
备选方案:命令/查询分离
我还需要强调的是,对于典型的分层架构,还有其他一些替代方案,例如命令/查询隔离方法,您可以通过调解器对命令和查询进行建模。我不会详细介绍它,因为它是另一个主题,但我肯定会更喜欢上面讨论的分层方法。这将导致您直接在建模命令或查询中将您的实体映射到您的 DTO。
我建议看一下 Mediatr为了这。同样创建 AutoMapper 的作者 Jimmy Bogard 也有 this video talking关于同一主题。
关于c# - Web API 应用程序中的模型分离,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35724115/