Миграции Entity Framework 4.3.1 всегда вызывают конструктор по умолчанию и игнорируют строку подключения

Я хочу выполнить (сначала код) миграцию, используя строку подключения, которую я создал сам.

Точка входа — это статическая функция с одним параметром — connectionString.

У меня есть класс DbContext с именем PocModel с конструктором по умолчанию.

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

И конструктор контекста со строковым аргументом:

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

Моя цель — выполнить миграцию базы данных, на которую нацелена строка подключения, а не строка подключения, которую EF «волшебным образом» создает только с помощью имени (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"]

В переданную строку подключения.

Но, увы, все терпит неудачу, и конструктор PocModel по умолчанию вызывается из кода миграции EF, ориентируясь на server:localhost\sqlexpress и базу данных:PocModel.

Мне не удалось выполнить миграцию в какую-либо базу данных без имени «PocModel», находящуюся на «localhost\sqlexpress».

Я не могу использовать файл app.config для установки моей строки подключения, так как мне нужно передать это через статическую внешнюю функцию.

Помогите пожалуйста, очень долго мучаюсь с этой проблемой.

РЕДАКТИРОВАТЬ: я заставил его работать с помощью этого взлома, но я задаю вопрос, чтобы убедиться, что действительно нет другого решения проблемы (иначе миграция 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)
        {

person Casper Leon Nielsen    schedule 08.08.2012    source источник


Ответы (3)


Вызов 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())
{ 

}
person Mark Oreta    schedule 08.08.2012
comment
Да, это то, что я реализовал сегодня. Однако я признаю, что это старый грязный хак, и искал правильный способ сделать это, не возясь с конструктором по умолчанию. Выполнение этого таким образом действительно полностью сводит на нет цель наличия конструктора не по умолчанию (его нельзя использовать). В любом случае, большое спасибо за ваш ответ, я не буду отмечать его как ответ, хотя он решает проблему. - person Casper Leon Nielsen; 08.08.2012

У меня была такая же проблема, как у вас. Однако я нашел решение, которое, как вы сказали, пробовали, но не сработало. Следующий код работал для меня. Я нашел его здесь 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();
person nialljt    schedule 07.03.2013
comment
Вы пробовали это, когда у вас был экземпляр Sql Server, работающий на localhost/SqlExpress? - person Casper Leon Nielsen; 07.03.2013

Для тех, кто обнаруживает, что их строка подключения игнорируется...

Похоже, в этой части фреймворка есть ошибка.

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 перед добавлением в средство миграции.

person Paul Devenney    schedule 22.06.2013