Fluent nhibernate 存储库和服务,MVC模型
所以我一直在学习关于存储库模型的知识,似乎可以预期存储库不会执行很多复杂的逻辑。然而,我也读到,大多数业务逻辑不应该在我的Fluent nhibernate 存储库和服务,MVC模型,fluent-nhibernate,service,asp.net-mvc-3,repository-pattern,Fluent Nhibernate,Service,Asp.net Mvc 3,Repository Pattern,所以我一直在学习关于存储库模型的知识,似乎可以预期存储库不会执行很多复杂的逻辑。然而,我也读到,大多数业务逻辑不应该在我的控制器中。那我把它放在哪里呢 我看了一些示例应用程序,它们似乎有另一个称为服务的层,它为事物提供更复杂的逻辑。那么这个因素是如何融入MVC模式的呢 我是否要构建我的服务以访问我的存储库,然后构建我的控制器以访问我的服务?像这样 interface IMembershipService { bool ValidateUser(string username, string p
控制器
中。那我把它放在哪里呢
我看了一些示例应用程序,它们似乎有另一个称为服务的层,它为事物提供更复杂的逻辑。那么这个因素是如何融入MVC模式的呢
我是否要构建我的服务以访问我的存储库,然后构建我的控制器以访问我的服务?像这样
interface IMembershipService
{
bool ValidateUser(string username, string password);
MembershipCreateStatus Create(string username, string password);
}
interface IMembershipRepository
{
MembershipCreateStatus Create(string username, string password);
}
class MembershipRepository : IMembershipRepository
{
public MembershipRepository(ISession session)
{
**// this is where I am confused...**
}
}
class MembershipService : IMembershipService
{
private readonly IMembershipRepository membershipRepository;
public MembershipService(IMembershipRepository membershipRepository)
{
this.membershipRepository = membershipRepository;
}
public bool ValidateUser(string username, string password)
{
// validation logic
}
public MembershipCreateStatus Create(string username, string password)
{
return membershipRepository.Create(username, password);
}
}
class MembershipController : Controller
{
private readonly IMembershipService membershipService;
public MembershipController(IMembershipService membershipService)
{
this.membershipService = membershipService
}
}
代码中标记的部分让我感到困惑。我读到的每一篇文章都说我应该将我的ISession
注入我的存储库。这意味着我不能将ISession
注入到我的服务中,那么如何从我的服务中访问数据库呢?我不明白这里的适当流程是什么
当我将ValidateUser
放入我的IMembershipRepository
中时,我被告知这是“坏的”。但是IMembershipRepository
是数据库访问所在的位置。这就是目的,对吗?使数据库访问量保持在最低限度?但是如果我不能把其他的逻辑放进去,那又有什么意义呢
有人能解释一下这一点,给我举个可能更可行的例子吗
我使用的是Fluent nHibernate
,ASP.NET MVC 3.0
,以及Castle.Windsor
我是不是应该做点像
class MembershipService
{
private readonly IMembershipRepository membershipRepository;
public MembershipService(ISession session)
{
membershipRepository = new MembershipRepository(session);
}
}
并且从不让我的控制器直接访问存储库
我读到的所有东西都说我应该把我的会话注入我的存储库
没错。您需要将会话注入到存储库构造函数中,因为这是进行数据访问的地方
这意味着我不能将ISession注入到我的服务中,那么如何从我的服务中访问数据库呢
在您的服务中不进行数据库访问。该服务依赖于注入其构造函数的一个或多个存储库,并使用它们各自的方法。该服务从不直接查询数据库
因此,总结一下:
- 存储库包含模型上的简单CRUD操作。这是执行数据访问的地方。这种数据访问并不一定意味着数据库。它将取决于您正在使用的底层存储。例如,您可以调用云上的一些远程服务来执行数据访问
- 该服务依赖于一个或多个存储库来实现业务操作。此业务操作可能依赖于存储库上的一个或多个CRUD操作。服务甚至不应该知道数据库的存在
- 控制器使用服务调用业务操作
- 为了减少不同层之间的耦合,使用接口来抽象操作
我读到的所有东西都说我应该把我的会话注入我的存储库
没错。您需要将会话注入到存储库构造函数中,因为这是进行数据访问的地方
这意味着我不能将ISession注入到我的服务中,那么如何从我的服务中访问数据库呢
在您的服务中不进行数据库访问。该服务依赖于注入其构造函数的一个或多个存储库,并使用它们各自的方法。该服务从不直接查询数据库
因此,总结一下:
- 存储库包含模型上的简单CRUD操作。这是执行数据访问的地方。这种数据访问并不一定意味着数据库。它将取决于您正在使用的底层存储。例如,您可以调用云上的一些远程服务来执行数据访问
- 该服务依赖于一个或多个存储库来实现业务操作。此业务操作可能依赖于存储库上的一个或多个CRUD操作。服务甚至不应该知道数据库的存在
- 控制器使用服务调用业务操作
- 为了减少不同层之间的耦合,使用接口来抽象操作
创建这样的服务是一种反模式
像这样的服务有多少责任?有多少原因需要改变
同样,如果你把你的逻辑放在服务中,你最终会得到一个贫乏的领域。最终得到的是事务脚本样式中的过程代码。我并不是说这一定不好
也许富域模型不适合您,但这应该是两者之间有意识的决定,而这种多重责任服务在这两种情况下都不合适
这应该是一个巨大的红旗:
public MembershipCreateStatus Create(string username, string password)
{
return membershipRepository.Create(username, password);
}
重点是什么?为了层而层?这项服务在这里没有任何价值,没有任何用途
缺少很多概念
首先,考虑使用工厂来创建对象:
public interface IMembershipFactory {
MembershipCreateStatus Create(string username, string password);
}
工厂可以封装用于构建实例或开始实体对象生命周期的任何逻辑
其次,存储库是对象集合的抽象。使用工厂创建对象后,将其添加到对象集合中
var result = _membershipFactory.Create("user", "pw");
if (result.Failed); // do stuff
_membershipRepository.Add(status.NewMembership); // assumes your status includes the newly created object
最后,MyEntityService
类包含一个方法,用于对实体执行的每个操作,这对我来说似乎是非常令人讨厌的
相反,我试图通过将每个操作建模为单个命令类,而不是单个服务类上的方法,来更明确、更好地捕获意图
public class ChangePasswordCommand {
public Guid MembershipId { get; set; }
public string CurrentPassword { get; set; }
public string NewPassword { get; set; }
}
然后,在发送此命令时,必须实际执行某些操作,因此我们使用处理程序:
public interface IHandle<TMessageType> {
void Execute(TMessageType message);
}
public class ChangePasswordCommandHandler : IHandle<ChangePasswordCommand> {
public ChangePasswordCommandHandler(
IMembershipRepository repo
)
{}
public void Execute(ChangePasswordCommand command) {
var membership = repo.Get(command.MembershipId);
membership.ChangePassword(command.NewPassword);
}
}
公共接口IHandle{
public interface IHandle<TMessageType> {
void Execute(TMessageType message);
}
public class ChangePasswordCommandHandler : IHandle<ChangePasswordCommand> {
public ChangePasswordCommandHandler(
IMembershipRepository repo
)
{}
public void Execute(ChangePasswordCommand command) {
var membership = repo.Get(command.MembershipId);
membership.ChangePassword(command.NewPassword);
}
}