Sam*_*Sam 7 asp.net-mvc unit-of-work repository-pattern service-layer entity-framework-4
我仍然很难绕过这个.我想像我这样分开我的图层(dll):
1)MyProject.Web.dll - MVC Web App(控制器,模型(编辑/查看),视图)
2)MyProject.Services.dll - 服务层(业务逻辑)
3)MyProject.Repositories.dll - 存储库
4)MyProject. Domain.dll - POCO类
5)MyProject.Data.dll - EF4
工作流程:
1)控制器调用服务以获取对象以填充视图/编辑模型.
2)服务调用存储库来获取/持久化对象.
3)存储库调用EF以从SQL Server获取/持久化对象.
我的存储库返回IQueryable(Of T),在其中它们使用ObjectSet(Of T).
所以我看到这一点,图层完全依赖于下一层和包含POCO类的lib?
一些问题:
1)现在我的存储库与EF一起正常工作,它们将依赖于System.Data.Objects,现在我在我的存储库层与EF紧密耦合,那是不是很糟糕?
2)我正在使用UnitOfWork模式.那住哪儿?它有一个Property Context As ObjectContext,因此它也与EF紧密耦合.坏?
3)我如何使用DI使这更容易?
我希望这是一个松散耦合的测试.有什么建议?
----------编辑----------
如果我在这里正确的轨道,请告诉我.另外,因此服务器注入一个IRepository(Of Category)权限,它如何知道它与EFRepository(Of T)的具体类之间的区别?与UnitOfWork和服务相同?
一旦有人帮助我把它弄清楚到我所理解的地方,我知道它看起来似乎微不足道,但是男人,我有一个时间包围我的头!
调节器
Public Class CategoryController
Private _Service As Domain.Interfaces.IService
Public Sub New(ByVal Service As Domain.Interfaces.IService)
_Service = Service
End Sub
Function ListCategories() As ActionResult
Dim Model As New CategoryViewModel
Using UOW As New Repositories.EFUnitOfWork
Mapper.Map(Of Category, CategoryViewModel)(_Service.GetCategories)
End Using
Return View(Model)
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
服务
Public Class CategoryService
Private Repository As Domain.Interfaces.IRepository(Of Domain.Category)
Private UnitOfWork As Domain.Interfaces.IUnitOfWork
Public Sub New(ByVal UnitOfWork As Domain.Interfaces.IUnitOfWork, ByVal Repository As Domain.Interfaces.IRepository(Of Domain.Category))
UnitOfWork = UnitOfWork
Repository = Repository
End Sub
Public Function GetCategories() As IEnumerable(Of Domain.Category)
Return Repository.GetAll()
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
存储库和UnitOfWork
Public MustInherit Class RepositoryBase(Of T As Class)
Implements Domain.Interfaces.IRepository(Of T)
End Class
Public Class EFRepository(Of T As Class)
Inherits RepositoryBase(Of T)
End Class
Public Class EFUnitOfWork
Implements Domain.Interfaces.IUnitOfWork
Public Property Context As ObjectContext
Public Sub Commit() Implements Domain.Interfaces.IUnitOfWork.Commit
End Sub
End Class
Run Code Online (Sandbox Code Playgroud)
不可以.但是,为避免将服务与此相关联,请ISomethingRepository在域层中使用接口.这将由您的IoC容器解决.
工作单元模式应该与您的存储库一起实现.使用相同的解决方案来解决这个问题,因为我建议将存储库与服务分离.创建一个IUnitOfWork或IUnitOfWork<TContext>在您的域层中,并将实现放在您的Repository层中.如果所有存储库都将数据保存到数据层,我认为您的存储库实现不需要与数据层分离,我认为没有任何理由ObjectContext. Repository接口是域逻辑,但实现是数据问题
您可以使用DI将服务注入控制器,将存储库注入服务.使用DI,您的服务将依赖于存储库接口ISomethingRepository,并将接收EFSomethingRepository不与数据/存储库程序集耦合的实现.基本上,您的IControllerFactory实现将使IoC容器为Controller提供所有构造函数依赖项.这将要求IoC容器还为其构造函数依赖项(存储库)提供所有控制器的构造函数依赖项(服务).所有程序集都依赖于您的域层(具有存储库和服务接口),但不会相互依赖,因为它们依赖于接口而不是实现.您将需要单独的程序集来进行依赖性解析,或者您需要在Web项目中包含该代码.(我会推荐一个单独的组装).唯一依赖于依赖关系解析程序集的程序集将是UI程序集,尽管如果使用IHttpModule实现在Application_Start事件中注册依赖项,即使这样也不是完全必要的(项目仍然需要bin中的dll副本文件夹,但不需要项目引用).有很多合适的开源IoC容器.最好的一个很大程度上取决于你的选择.我个人喜欢StructureMap.它和Ninject都是可靠且记录良好的DI框架.
我用VB编写代码已经好几年了,所以我的语法可能会关闭.
Public Class CategoryController
Private _Service As Domain.Interfaces.IService
'This is good.
Public Sub New(ByVal Service As Domain.Interfaces.IService)
_Service = Service
End Sub
Function ListCategories() As ActionResult
Dim Model As New CategoryViewModel
Using UOW As New Repositories.EFUnitOfWork
Run Code Online (Sandbox Code Playgroud)
这不需要在控制器中.将其移动到存储库并使其包围实际的事务.此外,您不希望控制器依赖于数据层.
Mapper.Map(Of Category, CategoryViewModel)(_Service.GetCategories)
Run Code Online (Sandbox Code Playgroud)
这是对AutoMapper的调用吗?与原始问题无关,但是,您应该将映射功能重定位到ActionFilter,以便返回只是返回视图(_Service.GetCategories)
End Using
Return View(Model)
End Function
Run Code Online (Sandbox Code Playgroud)
Service类没有问题.
存储库和工作单元看起来大部分都是不完整的.您的存储库应该新建ObjectContext并将其注入工作单元,然后执行工作单元范围内的所有事务(类似于您在控制器中执行的操作).在Controller中使用它的问题是,可能将单个Service调用范围限定为多个工作单元.这是一篇关于如何实施工作单元的好文章. http://martinfowler.com/eaaCatalog/unitOfWork.html.Martin Fowler的书籍和网站是关于这些类型主题的重要信息来源.
| 归档时间: |
|
| 查看次数: |
4001 次 |
| 最近记录: |