在我的项目中尝试实施EF迁移时,我被困在一个地方。
EF Code First MigrateDatabaseToLatestVersion接受来自config的连接字符串Name。
在我的案例中,数据库名称在运行时已知(用户从下拉列表中选择它)。 就像DbContext接受的方式,ConnectionString或connectionString Name在它的构造函数中,“MigrateDatabaseToLatestVersion”不接受相同的
System.Data.Entity.Database.SetInitializer (new MigrateDatabaseToLatestVersion<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(connString));
还有其他方法可以达到这个目的吗?
答案 0 :(得分:13)
谢谢大家。我从codeplex中检出了EF代码,并在理解了它们的源代码后继承了我自己的类。这是我选择的解决方案: -
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;
}
}
答案 1 :(得分:3)
这是在什么情况下运行?网站或桌面应用程序?
在网站下,这样做并不是一个好主意。数据库初始化策略根据上下文类型设置。因此,具有相同类型上下文的不同连接字符串将覆盖彼此的init策略。
如果桌面应用程序,可能包含一个额外的实用程序来在数据库之间切换?
无论哪种方式,我都不建议这样做,但如果你真的想做你提到的事情,看起来你必须破解它。
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();
}
答案 2 :(得分:3)
您可以使 MigrateDatabaseToLatestVersion 初始化程序使用首先触发迁移的上下文使用的连接字符串。 这是通过将 useSuppliedContext:true 传递给MigrateDatabaseToLatestVersion构造函数来完成的,如the docs中所述。在你的情况下:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<SrcDbContext, SRC.DomainModel.ORMapping.Migrations.Configuration>(useSuppliedContext: true));
答案 3 :(得分:0)
迁移的问题是使用参数调用DbContext派生类。一旦解决了它应该工作。请看这里的示例解决方案。 EntityFramework code-first custom connection string and migrations