MVC洋葱架构,一些问题

5
我正在使用Asp.net MVC 5,Web Api 2和Entity Framework创建一个项目。我正在使用洋葱架构进行设计,因此我有一个DAL,Service和UI层。
我的DAL层包含UnitOfWork和Repositories,我的Service层包含业务用例的服务。
但是我有以下问题:
  1. 我应该在哪里使用UnitOfWork的save(或commit)方法?在Services层还是UI层? 如果我在Services层中使用它,如何处理跨多个Services的情况?
  2. 我正在为WebApi操作使用DTOs,Services层应该返回DTOs还是映射应该在UI层中完成?
  3. DTOs应该在单独的项目中还是在UI项目中?如果它们在单独的项目中,我应该使用MVC属性进行验证吗?

1
在 EF 之上的存储库不好,好不好? - Inspector Squirrel
6
如果你曾经遇到过经理或架构师在项目进行中改变数据访问技术的想法,那么你会明白在数据访问框架上有一个抽象层的价值。因此,如果仓储库封装了ORM,那么在EF(或任何ORM)之上使用它们并不是不好的选择。 - Brian Driscoll
2
@Sippy 这不是什么坏事,大多数情况下也不是必需的,但我确实需要抽象出所有的Entity Framework实现,正如BrianDriscoll所说,可能会有数据访问方面的变化。 - Escobar5
1
@BrianDriscoll 同意。我经常创建相同的内容,这样我就可以在Mongodb和SQL Azure之间进行切换。我认为Sippy可能指的是每种类型模式的错误实践。 - Charlie Brown
1
也许对于问题1的提示,在DDD(领域驱动设计)中,您可以区分应用服务领域服务应用服务代表单个用例,而领域服务则表示对您的领域模型的操作。在这个空间里,工作单元通常由应用服务管理,它可以组合多个领域服务来实现应用程序中给定的用例。 - PermaFrost
显示剩余3条评论
1个回答

6

你的工作单元应该存在于你的服务层。每次对服务的调用都包含在一个单独的工作单元内进行业务交易。

    public ServiceResponse<Patient> Save(Patient patient, string userName)
    {
        Func<Patient> func = delegate
        {
            Authorize(patient, userName);
            Validate(patient, new PatientValidator());

            using (var context = _contextFactory())
            {
                return context.Save(patient, userName);
            }
        };
        return this.Execute(func);
    }

服务层应该返回您的业务实体,任何网络通信/JSON格式化的映射都应该在Web API中完成。这样可以最大限度地重用您的服务。
如果您指的是通过线路/JSON序列化使用的对象,则它们应该留在与Web API相同的项目中。这可能与您拥有UI的项目相同,也可能不同。如果您使用Web API,则建议使用FluentValidation等验证库。
使用C#,EF,Web API的洋葱架构示例 https://github.com/carbonrobot/FullStackEF

谢谢,还有一个问题,为什么你将所有保存功能都封装在委托中? - Escobar5
2
所以我可以为所有方法设置一个try...catch,并返回一个标准格式的响应对象。这使得来自客户端(如WebApi)的调用更加清晰,您可以使用通用方法处理响应。在该try...catch中也可以进行日志记录。由于所有操作都发生在该方法内部,因此所有错误都将被捕获、记录和处理。 - Charlie Brown
我想补充一点,你的业务对象并不等同于你的Entity Framework模型。 - Chris McKenzie
1
@ChrisMcKenzie 我不同意这个观点。拥有单独的模型并不是必要的,因为您可以按照自己的方式对领域进行建模,EF会处理映射细节。不应该存在任何阻抗不匹配。 - Charlie Brown

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接