C# 实体框架代码优先:为每个项目创建单独的数据库

C# 实体框架代码优先:为每个项目创建单独的数据库,c#,entity-framework,ef-code-first,structuremap,C#,Entity Framework,Ef Code First,Structuremap,我正在使用WPF和实体框架CodeFirst开发一个应用程序。 一个要求是用户可以为每个新项目创建单独的数据库文件。 DbContext: public class TestContext : DbContext, IUnitOfWork { public TestContext() : base("TestContext") { } #region Implementation of IUnitOfWork public new I

我正在使用WPF和实体框架CodeFirst开发一个应用程序。
一个要求是用户可以为每个新项目创建单独的数据库文件。
DbContext:

public class TestContext : DbContext, IUnitOfWork
{
    public TestContext()
        : base("TestContext")
    {
    }

    #region Implementation of IUnitOfWork

    public new IDbSet<TEntity> Set<TEntity>() where TEntity : class
    {
        return base.Set<TEntity>();
    }

    #endregion Implementation of IUnitOfWork

    public DbSet<Destination> Destinations { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new DestinationMap());
    }
public类TestContext:DbContext,IUnitOfWork
{
公共TestContext()
:base(“TestContext”)
{
}
#IUnitOfWork的区域实施
public new IDbSet Set(),其中tenty:class
{
返回base.Set();
}
#IUnitOfWork的endregion实现
公共数据库集目的地{get;set;}
模型创建时受保护的覆盖无效(DbModelBuilder modelBuilder)
{
添加(newdestinationmap());
}
应用程序配置中定义的连接字符串:

<connectionStrings>
    <clear />
    <add name="TestContext" providerName="System.Data.SqlClient" connectionString="Server=.\sqlexpress;Database=databaseName;Integrated Security=True;Connect Timeout=300;MultipleActiveResultSets=true;" />
</connectionStrings>
ObjectFactory.Initialize(x => x.Scan(scanner =>
{                                       
    x.For<IUnitOfWork>().CacheBy(InstanceScope.Hybrid).Use<SpitfireContext>();
}));


我已经使用StructureMap在IUnitOfWork接口中注入DbContext,以实现每个请求的上下文模式。 这是StructureMap配置:

<connectionStrings>
    <clear />
    <add name="TestContext" providerName="System.Data.SqlClient" connectionString="Server=.\sqlexpress;Database=databaseName;Integrated Security=True;Connect Timeout=300;MultipleActiveResultSets=true;" />
</connectionStrings>
ObjectFactory.Initialize(x => x.Scan(scanner =>
{                                       
    x.For<IUnitOfWork>().CacheBy(InstanceScope.Hybrid).Use<SpitfireContext>();
}));
ObjectFactory.Initialize(x=>x.Scan(scanner=>
{                                       
x、 For().CacheBy(InstanceScope.Hybrid).Use();
}));
当用户创建新项目时,我尝试更改连接字符串并强制应用程序为新项目创建数据库

public static void ChangeDatabase(Guid guid)
{
    var sqlConnectionStringBuilder =
        new SqlConnectionStringBuilder(ConfigHelper.ActiveConnection);
    sqlConnectionStringBuilder["Database"] = guid.ToString();
    ConfigHelper.ActiveConnection = sqlConnectionStringBuilder.ToString();
    Database.DefaultConnectionFactory =
        new System.Data.Entity.Infrastructure.SqlConnectionFactory(ConfigHelper.ActiveConnectionString());

    Database.SetInitializer(
        new MigrateDatabaseToLatestVersion<TestContext, MigrationConfiguration>());
    using (var context = new TestContext())
    {
        context.Database.Initialize(true);
    }
}
publicstaticvoidchangedatabase(Guid)
{
var sqlConnectionStringBuilder=
新的SqlConnectionStringBuilder(ConfigHelper.ActiveConnection);
sqlConnectionStringBuilder[“数据库”]=guid.ToString();
ConfigHelper.ActiveConnection=sqlConnectionStringBuilder.ToString();
Database.DefaultConnectionFactory=
新的System.Data.Entity.Infrastructure.SqlConnectionFactory(ConfigHelper.ActiveConnectionString());
Database.SetInitializer(
新的MigrateDatabaseToLatestVersion());
使用(var context=newtestcontext())
{
context.Database.Initialize(true);
}
}
应用程序只为第一个项目创建数据库,然后尝试迁移预览数据库。
我没有在代码中直接创建DbConext对象,因此无法将连接字符串传递给其构造函数。
你对我的问题有什么建议?

我的代码怎么了?

会在DbContext类中添加一个静态属性来存储数据库的名称(初始目录),然后更改连接字符串,以便插入带有字符串的数据库名称。格式化工作吗


然后,您可以随时更改数据库名称,下次创建上下文时,它将指向一个新的目标。

这是一个棘手的部分-更改连接字符串。它可以正常工作,但有问题

请看我的这篇(及相关)文章,它描述了基于类似方法的代码的一些故障背景

如果需要,我想进一步帮助你-但我需要更多信息

为什么说
我不直接在代码中创建DbConext对象,所以我不能将连接字符串传递给它的构造函数
?你有
测试上下文
-为什么不在那里传递它

另外,我不确定是否要设置
DefaultConnectionFactory
,我会重新检查。这是允许设置的,但似乎仅在应用程序启动时才建议设置,不确定。请同时查看此链接(这是针对EF6的,但我认为代码类似-您可以查看源代码)——

我们得出结论,在这种情况下使用DbContext工厂是有益的