实体框架4.3.1迁移始终调用默认构造函数并忽略连接字符串

时间:2012-08-08 11:12:36

标签: .net entity-framework database-migration

我想使用我自己构建的connectionString执行(代码优先)迁移。

入口点是一个带有一个参数的静态函数,connectionString。

我有一个名为PocModel的DbContext类,它带有一个默认构造函数。

public PocModel() : base("PocModel")
{ ...

带有字符串参数的上下文构造函数:

public PocModel(string nameOrConnectionString): base(nameOrConnectionString)
{ ...

我的目标是在connectionString所针对的数据库上执行迁移,而不是EF“神奇地”通过名称创建的connectionString(localhost \ sqlexpress - PocModel)。

这是我无法做到的。

我有一个像这样声明的“外部”函数:

public static void MigrateDatabase(string connectionString)
{ ...

我试图在flw中实现这个功能。方法:

 DbMigrator migrator = new DbMigrator(new Migrations.Configuration());
 migrator.Configuration.TargetDatabase = new  DbConnectionInfo(connectionString, "System.Data.SqlClient");
 migrator.Update();

就像这样:

Database.DefaultConnectionFactory = new SqlConnectionFactory(connectionString);
 Database.SetInitializer<PocModel>(new MigrationInitializer());
 PocModel model = new PocModel(connectionString);
 model.Dispose();

我甚至试图动态设置

ConfigurationManager.ConnectionString["PocModel"]

传入的connectionString。

但是,所有都失败了,默认的PocModel构造函数是从EF迁移代码中调用的,目标服务器是:localhost \ sqlexpress和database:PocModel。

我无法迁移到位于“localhost \ sqlexpress”上的名为“PocModel”的任何数据库。

我不能选择使用app.config文件来设置我的connectionString,因为我需要通过静态外部函数传递它。

请帮忙,现在已经坚持这个问题了很长时间。

编辑: 我已经通过这个hack使它工作了,但是我问这个问题是为了验证确实没有其他问题解决方案(也就是EF迁移有问题)

  private static string _databaseNameOrConnectionString = "PocModel";

        internal static string DatabaseNameOrConnectionString
        {
            get { return _databaseNameOrConnectionString; }
            //HACK: This setter must ONLY be called from SetupModule.MigrateDatabase. It is a hack to circumvent the code-first migrations usage of this ctor.
            set { _databaseNameOrConnectionString = value; }
        }

        //the code first migrations will call this ctor and ignore the connectionString it have been passed.
        public PocModel()
            : base(DatabaseNameOrConnectionString)
        {

3 个答案:

答案 0 :(得分:1)

Update-database调用正在使用默认构造函数,因此您必须修改该函数。你提到你有一个静态类来执行此操作,我无法找到一种在没有静态帮助器的情况下使其工作的方法。

 public static class Helper
    {
        public static string GetConnectionString()
        {
            SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
            builder.DataSource = @".\sqlexpress";
            builder.InitialCatalog = "migrateme";
            builder.IntegratedSecurity = true;
            builder.MultipleActiveResultSets = true;
            return builder.ConnectionString;
        }
    }

然后我调用构造函数而不是调用基础构造函数,并使用自定义字符串,并创建了正确的数据库

public PocModel() : base(Helper.GetConnectionString())
{ 

}

答案 1 :(得分:0)

我和你有同样的问题。但是我找到了一个解决方案,你说你尝试但没有工作。以下代码对我有用。我在http://romiller.com/2012/02/09/running-scripting-migrations-from-code/

找到了它
var configuration = new Configuration();
configuration.TargetDatabase = new DbConnectionInfo("Server=MyServer;Database=MyDatabase;Trusted_Connection=True;", 
    "System.Data.SqlClient");
var migrator = new DbMigrator(configuration);
migrator.Update();

答案 2 :(得分:0)

对于那些发现他们的连接字符串被忽略的人......

框架的这一部分似乎存在错误

var configuration = new TMigrationsConfiguration();
configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString,"System.Data.SqlClient");
var migrator = new DbMigrator(configuration);
migrator.Update();

的行为不同
var configuration = new TMigrationsConfiguration();
var migrator = new DbMigrator(configuration);
migrator.Configuration.TargetDatabase = new DbConnectionInfo(context.Database.Connection.ConnectionString,"System.Data.SqlClient");
migrator.Update();

即 - 如果在创建迁移器后更改了目标数据库,则会忽略该数据库。您必须在添加到迁移器之前设置TargetDatabase。