Код EF сначала MigrateDatabaseToLatestVersion принимает имя строки подключения из config
при попытке реализовать миграции EF в моем проекте я застрял в одном месте.
код EF сначала MigrateDatabaseToLatestVersion принимает имя строки подключения из config.
в моем случае имя базы данных становится известным во время выполнения (пользователь выбирает его из раскрывающегося списка). Точно так же, как DbContext принимает имя ConnectionString или connectionString в своем конструкторе, "MigrateDatabaseToLatestVersion" не принимает же
System.Data.Entity.Database.SetInitializer (new MigrateDatabaseToLatestVersion<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(connString));
есть ли другой способ добиться этого?
4 ответов
спасибо всем. Я проверил код EF из codeplex и унаследовал свой собственный класс после понимания их исходного кода. Вот решение, которое я выбрал :-
public class MigrateDbToLatestInitializerConnString<TContext, TMigrationsConfiguration> : IDatabaseInitializer<TContext>
        where TContext : DbContext
        where TMigrationsConfiguration : DbMigrationsConfiguration<TContext>, new()
    {
        private readonly DbMigrationsConfiguration config;
        /// <summary>
        ///     Initializes a new instance of the MigrateDatabaseToLatestVersion class.
        /// </summary>
        public MigrateDbToLatestInitializerConnString()
        {
            config = new TMigrationsConfiguration();
        }
        /// <summary>
        ///     Initializes a new instance of the MigrateDatabaseToLatestVersion class that will
        ///     use a specific connection string from the configuration file to connect to
        ///     the database to perform the migration.
        /// </summary>
        /// <param name="connectionString"> connection string to use for migration. </param>
        public MigrateDbToLatestInitializerConnString(string connectionString)
        {
            config = new TMigrationsConfiguration
                          {
                              TargetDatabase = new DbConnectionInfo(connectionString, "System.Data.SqlClient")
                          };
        }
        public void InitializeDatabase(TContext context)
        {
            if (context == null)
            {
                throw new ArgumentException("Context passed to InitializeDatabase can not be null");
            }
            var migrator = new DbMigrator(config);
            migrator.Update();
        }
    }
 public static class DatabaseHelper
    {
        /// <summary>
        /// This method will create data base for given parameters supplied by caller.
        /// </summary>
        /// <param name="serverName">Name of the server where database has to be created</param>
        /// <param name="databaseName">Name of database</param>
        /// <param name="userName">SQL user name</param>
        /// <param name="password">SQL password</param>
        /// <returns>void</returns>
        public static bool CreateDb(string serverName, string databaseName, string userName, string password)
        {
            bool integratedSecurity = !(!string.IsNullOrEmpty(userName) || !string.IsNullOrEmpty(password));
            var builder = new System.Data.SqlClient.SqlConnectionStringBuilder
                {
                    DataSource = serverName,
                    UserID = userName,
                    Password = password,
                    InitialCatalog = databaseName,
                    IntegratedSecurity = integratedSecurity,
                };
            var db = new SrcDbContext(builder.ConnectionString);
            var dbInitializer = new MigrateDbToLatestInitializerConnString<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(builder.ConnectionString);
            //following uses strategy to "CreateIfNotExist<>"
            dbInitializer.InitializeDatabase(db);
            return true;
        }
    }
в каком контексте это работает? Сайт или настольное приложение?
на веб-сайте это не очень хорошая идея. Стратегия инициализации базы данных, заданная в соответствии с типом контекста. Таким образом, разные строки соединения с одним и тем же типом контекста будут переопределять стратегию инициализации друг друга.
Если настольное приложение, возможно, включить дополнительную утилиту для переключения между базой данных?
в любом случае я не рекомендую делать это, но если вы действительно хотите сделать то, что вы упомянуто, похоже, что вы должны взломать его.
    using (var context = new DbContext("<Your connection string right in here>"))
    {
        var constructors = typeof (DbMigrator).GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic);
        var hackedDbMigrator = constructors[0].Invoke(new object[] { new Configuration(), context }) as DbMigrator;
        hackedDbMigrator.Update();
    }
можно сделать MigrateDatabaseToLatestVersion инициализатор для использования строки подключения, которая использовалась контекстом, который вызвал миграцию в первую очередь. Это делается путем прохождения useSuppliedContext: true в конструктор MigrateDatabaseToLatestVersion, как описано в документы. В вашем случае:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(useSuppliedContext: true));
проблема с миграциями вызывает DbContext dervied класс с параметром. Как только это будет решено, это должно сработать. см. здесь образец решения. EntityFramework code-первая пользовательская строка подключения и миграции
