Ich schreibe eine Webanwendung mit Entity Framework 6.1.3 Code zuerst und mit SQL Express Management Studio 2014. Ich verwende Migrationen für die Aktualisierung der DB jedes Mal, wenn meine Anwendung wächst. Das sieht gut aus und funktioniert sehr gut auf meiner eigenen db. Aber wenn ich diese Anwendung auf den Produktionsserver setze, möchte ich beim Ausführen der Anwendung zwei verschiedene Benutzer verwenden, einen db_owner-Benutzer, der die db-Struktur ändern kann, und einen db_read/write-Endbenutzer. Dafür hatte ich 2 Optionen:Verwenden anderer connectionString, wenn die Migration erforderlich ist oder nicht
1) Verwenden von zwei web.config-Dateien, mit verschiedenen connectionString innerhalb, die den Benutzer angeben, den ich brauche. Auf diese Weise führe ich bei jeder Migration zunächst den Build db_owner und nach der Aktualisierung erneut db_read/write one aus;
2) Finden Sie einen Weg, um der Anwendung mitzuteilen, dass einige ausstehende Migrationen vorhanden sind, und verbinden Sie zuerst mit dem Benutzer db_owner, wechseln Sie dann den Benutzer und setzen Sie die Ausführung fort.
Die zweite ist offensichtlich die beste Wahl.
Als ich mich umsah, fand ich ein paar Sachen heraus, die nicht für mich funktionierten.
ich in der web.config file:
<add name="UserWithPrivilegesConnectionString" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=MyDb-test; Persist Security Info=True; MultipleActiveResultSets=True; User ID=userWithPrivileges; Password=pass" providerName="System.Data.SqlClient" />
<add name="RandomUserConnectionString" connectionString="Data Source=.\SQLEXPRESS; Initial Catalog=MyDb-test; Persist Security Info=True; MultipleActiveResultSets=True; User ID=user; Password=pass" providerName="System.Data.SqlClient" />
in myInitializer.cs
Dann hinzugefügt haben
class myInitializer : System.Data.Entity.MigrateDatabaseToLatestVersion<MyDbContext, Configuration>
public override void InitializeDatabase(MyDbContextcontext)
{
try
{
context.SetConnectionString(System.Configuration.ConfigurationManager.ConnectionStrings["RandomUserConnectionString"].ConnectionString);
if (!context.Database.Exists() || !context.Database.CompatibleWithModel(false))
{
var configuration = new Configuration();
var migrator = new DbMigrator(configuration);
configuration.TargetDatabase = new DbConnectionInfo(System.Configuration.ConfigurationManager.ConnectionStrings["UserWithPrivilegesConnectionString"].ConnectionString, "System.Data.SqlClient");
var migrations = migrator.GetPendingMigrations();
if (migrations.Any())
{
var scriptor = new MigratorScriptingDecorator(migrator);
string script = scriptor.ScriptUpdate(null, migrations.Last());
if (!String.IsNullOrEmpty(script))
{
context.Database.ExecuteSqlCommand(script);
}
}
}
base.InitializeDatabase(context);
Wo context.Database.ExecuteSqlCommand(script);
ausgeführt wird, erhalte ich:
Exception thrown: 'System.Data.Entity.Core.EntityException' in EntityFramework.SqlServer.dll
Additional information: The underlying provider failed on Open.
Der Grund dafür ist, dass Kontext noch hat die RandomUserConnectionString innerhalb und kann keine Möglichkeit finden, es zu ändern. Ich habe auch versucht, eine setConnectionString-Methode für den Kontext, aber keine Möglichkeit hinzuzufügen. Ich habe auch versucht, einen anderen Ansatz, nach wie vor in myInitializer.cs
var configuration = new Configuration();
var migrator = new DbMigrator(configuration);
configuration.TargetDatabase = new DbConnectionInfo(System.Configuration.ConfigurationManager.ConnectionStrings["UserWithPrivilegesConnectionString"].ConnectionString, "System.Data.SqlClient");
var migrations = migrator.GetPendingMigrations();
if (migrations.Any())
{
migrator.update();
}
}
base.InitializeDatabase(context);
aber nichts. Ich habe auch versucht zu schließen, connectionString gesetzt und explizit Verbindung geöffnet.
FYI, MyDbContext
war
public MyDbContext() : base("name=UserWithPrivilegesConnectionString")
{
Configuration.LazyLoadingEnabled = false;
}
public MyDbContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
//disable initializer if necessary
Configuration.LazyLoadingEnabled = false;
}
und jetzt habe ich das Argument von dem ersten Basiskonstruktor entfernt.
Irgendwelche Ideen?
Ich bin mir da nicht sicher. Wie kann die Anwendung erkennen, wann der randomUserConnectionString verwendet werden soll? – Kernel
Sorry, ich habe die Fehlermeldung nicht sehr gut gelesen! Der zugrunde liegende Provider ist bei Open fehlgeschlagen. –
Wir verwenden Migrationsskripte, um unsere Nicht-Entwicklungsdatenbanken zu aktualisieren. http://cpratt.co/migrating-production-database-with-entity-framework-code-first/ –