3

我有两个使用以下 Unity 逻辑的项目:

container.RegisterType<IUnitOfWork, MyDbContext>(
    new HierarchicalLifetimeManager(),
    new InjectionFactory(
        c => new MyDbContext(configurationService.MySqlConnectionString)
    )
);
container.RegisterType<DbContext, MyDbContext>(
    new HierarchicalLifetimeManager()
);

第一个项目是一个使用Unity.MVC4包的 Web 应用程序,因此有一个定制的 DependencyResolver 来完成一些工作 -这非常有效

第二个是非 Web 应用程序,因此使用普通的Unity包实例,但在使用MyDbContext进行调用时出错。例外是

System.Data.Entity.Core.MetadataException:指定的架构无效。错误:EntityDataModel.MyProject.ssdl(2,2):错误 0152:实体框架提供程序类型 'System.Data.Entity.SqlServer.SqlProviderServices,EntityFramework.SqlServer,版本 = 6.0.0.0,文化 = 中性,PublicKeyToken = b77a5c561934e089'无法加载“System.Data.SqlClient”的 ADO.NET 提供程序。确保提供程序程序集可用于正在运行的应用程序。有关详细信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=260882

我已将两个项目设置为调用位于单独项目中的相同服务,以尝试将问题的根源与第二个项目的 Unity 逻辑隔离开来。我还应该注意我使用 Entity Framework 6 作为 ORM。

我的问题是我需要什么 Unity 代码才能使第二个项目工作,或者是否可以添加一些 app.config 条目来引用 EF 程序集?

更新: 经过一些额外的工作,我注意到如果我引用 DbContext 程序集:

  • 实体框架
  • EntityFramework.SqlServer

在第二个项目中,问题消失了。我想避免引用这些程序集,因为我的客户项目不应该对 ORM 有任何了解。

我也尝试过更新连接字符串,因此我手动指定了 ORM 项目的程序集(我的 EDMX 文件所在的位置),如StackOverflow 问题中所述,但这没有任何区别。

元数据=res://nameOfDll/Model.csdl|res://nameOfDll/Model.ssdl|res://nameOfDll/Model.msl

4

1 回答 1

2

您正在以正确的方式进行操作。

使用 DI,您可以从应用程序中删除依赖项。这样您就可以获得“与存储库无关”的应用程序。你已经有效地做到了。至少在“声明”依赖项的项目上。

但是,当应用程序必须运行时,您需要指定将用于“声明的”抽象依赖项(接口、抽象类)的具体对象。

您可以通过注册对象将用于每个抽象依赖项的类型来做到这一点。在您的示例中,当 aIUnitOfWork或 a时DbContext,提供 的实例MyDbContext

因此,“声明”依赖关系的项目完全独立于特定的实现。

但是,当您注册依赖类型时,您将失去这种独立性。

让我们看一个例子:

如果我说“我口渴了,我需要喝酒,但我不介意我喝什么”,我依赖于任何饮料,而不是特定的一种。但如果我说“口渴时我想喝可乐”,我就会依赖可乐。

第一部分是依赖的抽象定义:“任何饮料”(如抽象的IUnitOfWorkor DbContext)。第二部分是具体的依赖:“可乐”(​​如MyDbContext)。

所以,只要我不指定那是我想喝的东西,我就独立于可乐。但是一旦我说出来,我就会依赖。

也许您正在寻找的是一种在运行时更改存储库的方法。您可以这样做:不要在代码中注册依赖项,因为您需要使用所选的具体类型对项目进行引用。在外部配置(即文件)中执行此操作,这样您就可以在不引用依赖项的情况下编译项目,并在运行时提供所需的程序集。

注意:当我说“声明”时,我的意思是使用任何注入依赖项的模式,如构造函数注入(最建议)或任何其他注入模式(属性依赖项)。

于 2013-06-11T14:40:42.833 回答