gpt4 book ai didi

entity-framework - EF Code First、IoC 和 DbConnection

转载 作者:行者123 更新时间:2023-12-01 04:02:28 25 4
gpt4 key购买 nike

我首先使用实体​​框架代码。我希望能够注入(inject) System.Data.Common.DbConnection实例化派生自 System.Data.Entity.DbContext 的上下文时的对象.这样我就可以根据代码运行的环境传递不同类型的连接,即使用 System.Data.SqlClient (SQL Server) 正在开发中,System.Data.SQLite当单元测试和生产中的其他东西时。 Context的相关部分看起来像这样:

public class Context : DbContext
{
public Context(DbConnection dbConnection)
: base(dbConnection, true)
{
}

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<Context, Configuration>());

base.OnModelCreating(modelBuilder);
}

public DbSet<Test> Tests { get; set; }
}

这给了我以下错误: The target context 'Services.Persistence.Context' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory.我认为这发生在模型初始化期间,当 Entity Framework 显然觉得它需要更新它自己的 Context ,独立于我试图实现的 IoC 模式。缺少默认构造函数是设计使然。 IDbContextFactory接口(interface)同样没用——它也必须有一个默认构造函数。

Entity Framework Code First 是否完全符合通过从配置文件中读取连接字符串(或者直接传递连接字符串)来设置它的配置的想法,还是可以解决这个问题?

更新,这里是温莎配置:
container.Register(Component
.For<DbConnection>()
.UsingFactoryMethod(() =>
new SqlConnection("Data Source=(localdb)\\v11.0;Database=ThatProject;MultipleActiveResultSets=true"))
.LifeStyle.Transient);

container.Register(Component
.For<Context>()
.UsingFactoryMethod(k => new Context(k.Resolve<DbConnection>()))
.LifeStyle.PerWebRequest);

container.Register(Component
.For<IRepository>()
.UsingFactoryMethod(k => new Repository(k.Resolve<Context>()))
.LifeStyle.PerWebRequest);

最佳答案

我很确定您的问题与 EF 无关,但我并不是 Windsor 的真正用户,所以我不能确定您的配置问题是什么。我所做的是使用 ninject 重现类似的配置,它的工作方式完全符合您的预期,见下文:

class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel();
kernel.Bind<DbConnection>().ToMethod((ctx) =>{return new SqlConnection("Data Source=(localdb)\\v11.0;Database=ThatProject;MultipleActiveResultSets=true");});
kernel.Bind<Context>().ToSelf();//not really needed
kernel.Bind<TestRepository>().ToSelf();//not really needed
kernel.Get<TestRepository>();
}
}
public class Context : DbContext
{
public Context(DbConnection dbConnection)
: base(dbConnection, true){}

public DbSet<Test> Tests { get; set; }
}
public class TestRepository
{
public TestRepository(Context c)
{
c.Tests.Add(new Test());
c.SaveChanges();

var all = c.Tests;
}
}
public class Test
{
public int Id { get; set; }
}

这意味着 EF 不会尝试对上下文创建做任何有趣的事情(因为非空构造函数对我来说很好用)。

从您的 Windsor 配置中,我希望您需要执行以下操作,但我不太确定确切的语法:
container.Register(Component
.For<DbConnection>()
.UsingFactoryMethod(() =>
new SqlConnection("Data Source=(localdb)\\v11.0;Database=ThatProject;MultipleActiveResultSets=true"))
.LifeStyle.Transient);

container.Register(Component
.For<Context>()
.ImplementedBySelf()//this probably isn't the correct syntax
.LifeStyle.PerWebRequest);//per request is good, i have some details around why this is good practice if you are interested

container.Register(Component
.For<IRepository>()
.ImplementedBy<ConcreteRepository>()//you arent really calling a method and creating the object yourself you are letting Windsor create the object and sort out the dependancy tree
.LifeStyle.PerWebRequest);

关于entity-framework - EF Code First、IoC 和 DbConnection,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12664636/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com