我的服务层方法是否应该完全封装一个工作单元?

时间:2014-01-10 01:26:20

标签: c# entity-framework repository-pattern

我正在考虑重构我的一些C#代码,其中我使用Entity Framework 6实现了存储库模式。它是一个ASP.NET MVC4网站。目前,我在我的存储库之上有一个服务层。服务层保存我的业务逻辑,例如获取X大于Y的所有用户等

我的类似项目,具有相同的实现:https://github.com/ryancole/BetterArmory

现在,我的图书馆的客户端会像我这样使用我的库(为了简洁而没有DI):

using (var context = new MyDbContext())
{
    var userRepository = new MyUserRepository(context);
    var userService = new MyUserService(userRepository);

    var user = userService.getById(1);

    user.Name = "Foo Bar";

    context.SaveChanges();
}

上面,MyDbContext是我的类,它继承自EF6的DbContext。我的MyUserRepository存储库类和所有其他存储库将上下文作为arg。此外,服务类将适当的存储库类作为arg。

所以,我正在考虑以某种方式重构的事情是这种实现的漏洞,我觉得。在大多数情况下,从我的服务层返回的类是EF6代理,可以使用SaveChanges方法直接修改DbContext,保存这些更改。这对我来说很难进行验证,因为我正在使用Fluent验证,而EF似乎并不真正了解它。据我所知,我必须在我的服务层方法中从Fluent Val手动调用Validate。这很糟糕,因为代理对象的这些直接更改不是通过服务层方法执行的。即使我有一个名为SetUserEmail的服务层方法,其中我用Fluent Val验证了实体,用户仍然可以直接编辑代理属性。

所以我想知道,或许最好让我的服务层初始化DbContext,存储库并执行更改,调用任何所需的Fluent Val等等,所有这些都在一个函数中?

我的头顶部分可能是懒惰的加载必须在服务方法中明确,或者只是一起禁用并加载所有内容。这就是我现在所能想到的,但我知道我之前有其他的缺点。

1 个答案:

答案 0 :(得分:1)

对我而言,将UoW(在本例中为DbContext)封装到服务层中是有意义的。服务是一种事务行为,可以将一个或多个数据库操作跨越到一个事务中,如果一个操作失败,整个服务应该失败。

通常,应用程序层不应该知道DbContext及其存储库。它应该将所有逻辑操作委托给服务层。在MVC的情况下,这将导致瘦的控制器,其唯一的责任是根据服务调用的结果决定正确的路由/重新路由。

可以在服务层中进行延迟加载,加载所有内容都会导致严重的性能问题。

我已经构建了一个在线脚手架工具来演示这种架构。如果您有兴趣,可以在Camote Q查看。