仍然对存储库和解耦、ASP.NET MVC 迷失方向
我仍然在永恒地追求构建(和理解)解耦、IoC、DI 等现代编程约定。我正在尝试弄清楚如何构建存储库。我已经检查了 数据库抽象层设计 - 使用 IRepository 的帖子正确的方法?这非常有帮助,但我仍然遇到一些问题一直困扰着我。
我的程序现在有 4 层......
Web(项目 | ASP.NET MVC 应用程序)- 引用 Models.dll 和 Persistence.dll
模型(域对象)
持久性(域对象的流畅 nHibernate 映射)
实用程序(提供程序、存储库)
现在,我正在尝试编写一个简单的会员存储库。我的第一个任务...?
当有人尝试注册时检查电子邮件地址是否存在。这看起来一切都很好——所以我去尝试找出把它放在哪里。
但首先,我只是将其放置在 MembershipProvider
类 CreateUser
方法中。然而,这属于公用事业项目。到目前为止,Utilities 还不了解 nHibernate。只有 Persistence Project 才了解 nHibernate。
那么,我的 CreateUser 方法需要查询我的数据库。那么这里的最佳实践是什么?我是否要在 Persistence
项目中创建一个 UserRepository
,然后创建一个名为 CheckEmail
的完整方法?或者我是否只需将 nHibernate .dll 添加到我的 Utilities
项目中,并在提供程序中编写会话查找?
在我的持久性项目中创建执行特定操作的存储库似乎比创建提供者需要做更多的工作。如果我必须为它们创建存储库,为什么我还要创建提供者?所有这些新方法的目的不就是为了阻止代码重复吗?但感觉就像要让事情“分开”一样,我必须编写相同的代码 2 或 3 次。这里的最佳实践是什么?
I'm still on my eternal quest to build (and understand) modern programming convention of decoupling, IoC, DI, etc. I'm to the part where I am trying to figure out how to build a repository. I've examined the post at Database abstraction layer design - Using IRepository the right way? which was very helpful, but I've still got some problems that are just befuddling me all the way.
I have my program in now 4 layers...
Web (Project | ASP.NET MVC Application) - References Models.dll and Persistence.dll
Models (Domain Objects)
Persistence (Fluent nHibernate Mapping of Domain Objects)
Utilities (Providers, Repositories)
Now then, I'm trying to write up a simple Membership Repository. My first task... ?
Check to see if an email address exists when someone tries to register. That seemed all well and good - so I go to try and figure out where to place this.
At first though, I would just place it inside of the MembershipProvider
class CreateUser
method. This, however, resides in the Utilities project. So far, Utilities has no knowledge of nHibernate. Only the Persistence Project has any knowledge of nHibernate.
So then, my CreateUser
method needs to query my database. So what's the best practice here? Do I create a UserRepository
in the Persistence
project, and just make an entire method called CheckEmail
? Or do I simply add the nHibernate .dll's to my Utilities
project, and write session lookup within the Provider?
It seems like more work to make repositories in my Persistence Project that do specific actions than it is to make the providers. Why am I even making the Providers if I have to make Repositories for them? Isn't the purpose of all of these new methods to stop code repetition? But it feels like to keep things 'separate' I have to write the same code 2 or 3 times. What is the best practice here?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的存储库确实应该在您的持久性程序集中实现。假设您正在对它们进行单元测试,您将为域程序集中的每个存储库定义接口。
您的
CreateUser
方法不应直接查询数据库来确定电子邮件地址是否已存在,而应在DoesEmailExist
中创建一个单独的方法来负责执行该检查。每个方法都应该有一个单一的职责。回应jfar的疑惑:
没错,domain定义了可以做什么,定义了
Domain.IUserRepository.Create(User user)
等接口。然而,该域没有定义任何实现。假设您开始使用实体框架,您可能会创建一个实现域中定义的接口的
Persistence
程序集。因此,从上面的域接口开始,我们实现了该接口:例如,假设您的客户后来告诉您实现 NHibernate 持久层。幸运的是,我们的域与现有的持久层是分开的——它位于域中。因此,您可以轻松实现现有的域接口,而无需更改 MVC 应用程序中的任何代码 - 因为只知道您定义的接口,而不是实体框架实现。
然后,您的 IoC 容器可以配置为将
IUserRepository
解析为实体框架或 NHibernate 实现,您的 MVC 应用程序并不关心这两种方式。就程序集引用而言,
Persistence
程序集具有对Domain
的引用,而Domain
完全正确地没有对Domain
的引用>持久性。这导致了解耦设计,易于测试和更改,从而更容易维护。
我希望这有帮助。
Your repositories should really be implemented in your Persistence assembly. Assuming you are unit testing them, you would define the interface for each repository in your Domain assembly.
Your
CreateUser
method shouldn't be directly querying the database to determine if the email address already exists, instead create a separate method in yourDoesEmailExist
which is responsible for doing that check. Each method should have a single responsiblity.In response to jfar's doubts:
That's right, the domain defines what can be done, defining interfaces such as
Domain.IUserRepository.Create(User user)
. The domain does not however define any implementation.Let's say you start out using Entity Framework, you might create a
Persistence
assembly which implements the interfaces defined in the domain. So following on from the domain interface above we implement the interface:Let's say for example that your customer later tells you to implement an NHibernate persistence layer. Luckily our domain is separate to the existing persistence layer - it's in the domain. So you can easily implement the existing domain interfaces without needing to change any code in your MVC application - as all that knows about is the interface you defined, not the Entity Framework implementation.
Your IoC container can then be configured to resolve
IUserRepository
as either the Entity Framework or NHibernate implementation, your MVC application doesn't care either way.In terms of assembly references, the
Persistence
assembly has a reference to theDomain
, and theDomain
quite rightly does not have a reference toPersistence
.This leads to a decoupled design which is easy to test, and change going forwards, resulting in easier maintenance.
I hope that helped.
存储库接口应该放置在域层上,该存储库的实现将是基础设施层上的 NHibernate 类。你的 UI 层了解基础设施,但仅依赖于手动或通过 DI 容器注入的存储库接口。
The Repositories Interface should be placed on the Domain Layer, the implementation of this Repositories are going to be NHibernate classes on the Infrastructure Layer. Your UI Layer knows about the infrastructure, but will only depend on the repository interface which will be injected by hand or via DI container.
我使用以下约定来帮助我决定如上所述的功能:
案例:在用户注册时检查电子邮件地址是否已存在
1 - 验证类型:输入验证< br>
描述:是有效格式、长度、字符等的电子邮件。
完成者:设置属性时的User对象,否则会抛出异常
2 - 验证类型:业务规则验证
描述:是否已存在具有相同电子邮件地址的用户或任何此类业务规则?
完成者: UserRepository,因为它将能够在调用 Commit 之前查询所有用户以查找此信息
基于此,我的用户代码将如下所示:
所以,虽然我明白您在查看所有层时遇到困难,我将它们分类为:
Web 项目 - 是应用程序的视图部分&将只有数据逻辑来输出视图
模型 - POCO 具有验证自身的逻辑
存储库 - 如果对象有效且有效,则调用持久层所有业务规则均有效
持久层 - 将数据持久保存到存储
IoC/DI - 将解析实例和实例为您提供使用
HTH 的正确实例
I use the following convention to help me decide for functionality like you described above:
Case: Check if email address already exists when a user registers
1 - Validation Type: input validation
Description: is the email in the valid format, length, characters etc.
Done by: The User object when the property is set, else it will throw an exception
2 - Validation Type: business rule validation
Description: does a user with the same email already exist or any such business rule?
Done by: The UserRepository as it will be able to query across all the users to find this information before the Commit is called
Based on this, my code for the user would look like:
So, while I understand you are having trouble looking at all the layers, I would categorize them as:
Web Project - is the View part of your application & will have only databing logic to output a view
Models - a POCO's with logic to validate themselves
Repository - calls the persistance layer if the object is valid & all the business rules are valid
Persistance layer - persists the data to the store
IoC/DI - will resolve instances & give you the correct instance to work with
HTH
史黛西,看看这个视频。该视频是使用 ASP.NET MVC1 编写的,我认为它的质量非常高。观看视频并研究它。 MVC2 基本相同,只是改进了 Html 助手。
链接书呆子晚餐
我同意 Spolto 的观点:MVC 鼓励关注点分离,从而生产出可以测试的高质量软件。
Stacey, Take a look at this video. The video was prepared using ASP.NET MVC1, and I think that it is extremely high quality. Watch the video and study it. MVC2 is basically the same with an improved Html helper.
link Nerd Dinner
I agree with Spolto: MVC encourages the separation of concern and therefore produce high quality software which can be tested.