所以我一直在学习Repository模型,似乎预计Repositories不会做很多错综复杂的逻辑。但是我也读到大多数业务逻辑不应该在我的Controllers
内。那我该把它放在哪里呢?
我查看了一些示例应用程序,似乎他们有另一个名为Services
的层,它为事物做了更复杂的逻辑。那么这个因素如何影响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);
}
}
永远不要让我的控制器直接访问Repositories
?
答案 0 :(得分:4)
我读到的所有内容都说我应该将我的ISession注入我的存储库。
这是对的。您需要将会话注入到存储库构造函数中,因为这是进行数据访问的地方。
这意味着我无法将ISession注入到我的服务中,那么如何从我的服务中进行数据库访问?
您不在服务中进行数据库访问。该服务依赖于注入其构造函数的一个或多个存储库,并使用它们各自的方法。该服务从不直接查询数据库。
所以回顾一下:
答案 1 :(得分:1)
interface IMembershipService
{
bool ValidateUser(string username, string password);
MembershipCreateStatus Create(string username, string password);
}
创建像这样的反模式服务。
这样的服务有多少责任?有多少理由可以改变?
此外,如果您将逻辑置于服务中,您将最终陷入贫血领域。您最终将得到的是事务脚本样式中的过程代码。而且我并不是说这一定是坏事。
也许丰富的域名模型不适合您,但它应该是两者之间的有意识的决定,并且这种多重责任服务在这两种情况下都是不合适的。
这应该是巨大红旗:
public MembershipCreateStatus Create(string username, string password)
{
return membershipRepository.Create(username, password);
}
有什么意义?层为图层?该服务在这里没有任何价值,没有任何用处。
缺少很多概念。
首先,考虑使用Factory创建对象:
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
类包含可以在实体上执行的每个操作的方法,这似乎对我的感觉非常冒犯。
相反,我尝试通过将每个操作建模为不是单个Service类上的方法,而是作为单独的Command类来更明确和更好地捕获意图。
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);
}
}
使用与IoC容器接口的简单类调度命令。
这有助于避免整体服务类,并使项目的结构和逻辑位置更加清晰。