【问题标题】:Entity Framework Context - I'm Stuck!实体框架上下文 - 我卡住了!
【发布时间】:2011-03-07 14:08:12
【问题描述】:

好的,我之前已经就此问过一些问题,但我真的很难理解这一点。

我正在使用 Service/Repository/EF 4 w/Pocos 方法,我设置了 Ninject 并将服务注入控制器,但我试图找出在哪里注入上下文?

我希望能够在控制器上使用多个服务,而这些服务又可以使用相同的上下文访问多个存储库,因此所有更改都会一次持久化。

我研究了 UnitOfWork 模式,但我不明白 MVC(控制器)将如何实现这一点,因为他们只知道服务层和域实体。

编辑

正如 Mohamed 下面建议的那样,将上下文注入到存储库中,然后使用它的每个请求实例。如何在 MVC 应用程序中配置绑定?我会假设是这样的:

Bind(Of IContext).To(MyDataContext)

问题是,MVC 应用程序对上下文一无所知,对吧?

编辑 2

Public Class ProductController
    Private _Service As IProductService

    Public Sub New(Service As IProductService)
        _Service = Service
    End Sub

End Class

Public Class NinjectWebModule

    Public Sub New()
        Bind(Of IProductService).To(ProductService)
    End Sub

End Class

Public Interface IProductService

End Interface

Public Class ProductService
    Implements IProductService

    Private _Repository As IRepository(Of Product)

    Public Sub New(Repository As IRepository(Of Product))
        _Repository = Repository
    End Sub

End Class

Public Class NinjectServiceModule

    Public Sub New()
        Bind(Of IRepository(Of Product)).To(EFRepository(Of Product))
    End Sub

End Class

Public Interface IRepository(Of T As Class)

End Interface

Public Class EFRepository(Of T As Class)
    Implements IRepository(Of T)

    Private _UnitOfWork As MyUnitOfWork

    Public Sub New (UnitOfWork As IUnitOfWork)
        _UnitOfWork = UnitOfWork
    End Sub

End Class

Public Class NinjectRepositoryModule

    Public Sub New()
        Bind(Of IUnitOfWork).To(EFUnitOfWork).InRequestScope()
    End Sub

End Class

Public Interface IUnitOfWork
    Sub Commit()
End Interface

Public Class EFUnitOfWork()
    Implements IUnitOfWork

    Public Property Context As MyContextType

    Public Sub New()
        _Context = New MyContextType
    End Sub

End Class

然后我会从 MVC 应用注册所有三个模块?

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    您需要的组件:

    1. 存储库(通用或特定)
    2. 工作单元
    3. 服务
    4. 控制器

    每个是什么:

    1. 存储库:针对提供的上下文执行查询
    2. 工作单元:包装实体框架 ObjectContext
    3. 服务:调用存储库上的方法
    4. 控制器:调用服务上的方法,并调用工作单元上的“提交”。

    这样,你的 Controller 的 ctor 应该是这样的:

    public ProductController(IUnitOfWork unitOfWork, IProductService productService)
    

    您需要 UoW,因为您提到要跨多个存储库进行更改(一个相当常见的场景)。因此,通过将 UoW(即底层的 ObjectContext)传递给存储库,您可以启用它。

    使用 DI 容器将工作单元设置为 Http Context scoped.

    【讨论】:

    • @RPM1984 - 好的,所以我将在 repositories 项目中创建一个解析上下文的 Ninject 模块,一个在解析存储库的服务层中,一个在解析服务的 mvc 应用程序中,然后从 mvc 应用程序注册所有这些?因此,在存储库项目中,我将有一个实现 IUnitOfWork 的 EFUnitOfWork,并且将具有 MyProjectCotext 类型的 Context 属性,然后 Ninject 模块将 Bind(Of IUnitOfWork).To(Of EFUnitOfWork) 并根据请求进行限定?跨度>
    • @Sam Striano - 准点!总结的很好。 :) 最好的办法是开始,看看你怎么走 - 回来告诉我们你遇到了什么问题/你是如何开始的,我们会从那里开始。不过,不确定您所说的“模块”是什么意思。您应该只有一个注册表 - 在 Web 层中。所有组件(存储库/服务/控制器)都应该在接口上工作,因此“不关心”实际的实现。
    • @RPM - Ninject 绑定必须知道具体的实现,对吧?那么你会如何告诉它关于 EFUnitOfWork 并保留 SoC 呢?如果您愿意,请参阅我上面的编辑。
    • @Sam Striano - 我认为您对 SoC添加程序集参考 感到困惑。当然,您的 Web 层将需要对所有“其他层”的程序集引用,因此存在依赖关系,但它依赖于实现的“存在”,而不是实际实现本身。 SoC 是关于抽象、基于接口的编程、松散耦合——所有这些仍然可以实现。您的 Web 项目仍然对如何实现工作单元或存储库一无所知,只知道接口。
    • @RPM - 谢谢...所以我把它归结为只有我的存储库层和我的数据层(包含 EF 模型和上下文)是唯一两个引用 System.Data.Entity 的 dll .我真的看不到存储库层中引用的任何方法,因为 EFRepository 的具体实现依赖于 EF。在我看来,您真的不测试您的存储库,而是在测试您的服务层和控制器时提供它们?
    【解决方案2】:

    在存储库类中注入 ObjectContext 怎么样?并为每个请求使用单个实例?

    更新

    见这个例子ASP.NET MVC 3 Application using Ninject, Entity Framework 4 Code-First CTP 5, Patterns

    更新 2

    此示例适用于 NHibernate 会话,但与 EF ObjectContext 或 LinqToSQL DataConext 或类似内容的想法完全相同。真是很好的例子。检查并告诉我你的想法。

    http://www.itslet.nl/?p=904

    更新 3

    您定义 DI 绑定的地方当然必须了解所有具体实现。如果你真的希望你的 MVC 代码不知道上下文,你要么

    • 将该代码放入确实知道它的新项目中,
    • 或使用 XML 进行绑定(Ninject 站点本身有关于如何执行此操作的文档,但这不是此特定 DI 容器的默认预期用途),
    • 或使用 Ninject 模型(基本上这意味着拆分绑定,因此,您可以在与上下文相同的项目中拥有一个执行上下文投标的模块,而 MVC 只使用所有可发现的 Ninject 模块进行绑定)。李>

    这是使用 Ninject 模块的一个示例:What is the intention of Ninject modules?

    【讨论】:

    • @Mohamed - 听起来很棒,但我该怎么做呢?你有一个例子或一个链接吗?谢谢!!
    • 在我的回答中也检查 Update 2
    • @Mohamed - 看起来不错,但是 MVC 应用程序不是必须知道 EF 上下文,并且它会因此紧密耦合吗?如果我错了,请纠正我。谢谢!!
    • @Mohamed - 好的,所以我会在 mvc 应用程序中使用我的模块来解析服务,然后在我的服务层(单独的 dll)中我会使用我的模块来解析存储库的上下文然后在 global.asax 中注册它和 mvc 模块? - 非常感谢您的帮助!!
    猜你喜欢
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 2012-12-24
    • 2011-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多