存储库和服务,MVC 模型
所以我一直在学习Repository模型,似乎预计Repositories不会做很多复杂的逻辑。不过,我还了解到,大多数业务逻辑不应该位于我的控制器内部。那么我该把它放在哪里呢?
我查看了一些示例应用程序,似乎它们有另一个层,称为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);
}
}
并且永远不要让我的控制器直接访问存储库
?
So I've been learning about the Repository model, and it seems that it is expected that Repositories do not do a lot of intricate logic. However I also read that most of the business logic should not be inside of my Controllers
. So where do I put it?
I've looked at some sample applications and it seems that they have another layer called Services
that do more intricate logic for things. So how does this factor into the MVC pattern?
Do I want to build my services to access my repositories, and then my controllers to access my services? Like this?
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
}
}
The marked part of my code is what confuses me. Everything I have read said I should be injecting my ISession
into my repositories. This means I could not be injecting ISession
into my services, so then how do I do Database access from my Services? I'm not understanding what the appropriate process is here.
When I put ValidateUser
in my IMembershipRepository
, I was told that was 'bad'. But the IMembershipRepository
is where the database access resides. That's the intention, right? To keep the database access very minimal? But if I can't put other logic in them, then what is the point?
Can someone shed some light on this, and show me an example that might be more viable?
I am using Fluent nHibernate
, ASP.NET MVC 3.0
, and Castle.Windsor
.
Should I instead do something like ...
class MembershipService
{
private readonly IMembershipRepository membershipRepository;
public MembershipService(ISession session)
{
membershipRepository = new MembershipRepository(session);
}
}
And never give my Controllers direct access to the Repositories
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是正确的。您需要将会话注入存储库构造函数,因为这是进行数据访问的地方。
您不在服务中进行数据库访问。该服务依赖于注入到其构造函数中的一个或多个存储库并使用它们各自的方法。该服务从不直接查询数据库。
回顾一下:
That's correct. You need to inject the session into the repository constructor because this is where the data access is made.
You don't do database access in your services. The service relies on one or more repositories injected into its constructor and uses their respective methods. The service never directly queries the database.
So to recap:
创建这样的服务是一种反模式。
这样的服务有多少责任?有多少理由必须改变?
另外,如果你将逻辑放入服务中,你最终会得到一个贫乏的领域。您最终将得到事务脚本样式的过程代码。我并不是说这一定是坏事。
也许丰富的领域模型不适合您,但这应该是两者之间有意识的决定,并且这种多重责任服务在任何一种情况下都不合适。
这应该是一个巨大危险信号:
有什么意义?为了层而层?该服务不会增加任何价值,也没有任何作用。
有很多概念缺失。
首先,考虑使用工厂来创建对象:
工厂可以封装构建实例或开始实体对象生命周期的任何逻辑。
其次,存储库是对象集合的抽象。使用工厂创建对象后,将其添加到对象集合中。
最后,
MyEntityService
类包含可以在实体上执行的每个操作的方法,这对我来说似乎非常令人反感。相反,我尝试通过将每个操作建模为单独的命令类而不是单个服务类上的方法来更明确并更好地捕获意图。
然后,当发送此命令时,必须执行某些操作,因此我们使用处理程序:
使用与 IoC 容器交互的简单类来分派命令。
这有助于避免单一的服务类,并使项目的结构和逻辑位置更加清晰。
Creating a service like this an anti-pattern.
How many responsibilities does a service like this have? How many reasons could it have to change?
Also, if you put your logic into services, you are going to end up with an anemic domain. What you will end up with is procedural code in a Transaction Script style. And I am not saying this is necessarily bad.
Perhaps a rich domain model is not appropriate for you, but it should be a conscious decision between the two, and this multiple responsibility service is not appropriate in either case.
This should be a HUGE red flag:
What is the point? Layers for the sake of layers? The Service adds no value here, serves no purpose.
There are a lot of concepts missing.
First, consider using a Factory for creating objects:
The factory can encapsulate any logic that goes into building an instance or beginning the lifetime of an entity object.
Second, Repositories are an abstraction of a collection of objects. Once you've used a factory to create an object, add it to the collection of objects.
Lastly,
MyEntityService
class that contains a method for every operation that can be performed on an Entity just seems terribly offensive to my senses.Instead, I try to be more explicit and better capture intent by modeling each operation not as a method on a single Service class, but as individual Command classes.
Then, something has to actually do something when this command is sent, so we use handlers:
Commands are dispatched using a simple class that interfaces with our IoC container.
This helps avoids monolithic service classes and makes a project's structure and location of logic much clearer.