1

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?

+0

Ich bin mir da nicht sicher. Wie kann die Anwendung erkennen, wann der randomUserConnectionString verwendet werden soll? – Kernel

+0

Sorry, ich habe die Fehlermeldung nicht sehr gut gelesen! Der zugrunde liegende Provider ist bei Open fehlgeschlagen. –

+0

Wir verwenden Migrationsskripte, um unsere Nicht-Entwicklungsdatenbanken zu aktualisieren. http://cpratt.co/migrating-production-database-with-entity-framework-code-first/ –

Antwort

0

Standardmäßig verwenden EF-Migrationen dieselbe Verbindungszeichenfolge, die Sie in Ihrem DbContext verwenden. Sie können sie jedoch in Ihrer DbMigrationsConfiguration-Unterklasse ändern (Konfiguration und im Migrationsordner erstellt, wenn Sie Migrationen für ein Projekt aktivieren). im Konstruktor, fügen Sie einfach:

TargetDatabase = new DbConnectionInfo(ConfigurationManager.ConnectionStrings["UserWithPrivilegesConnectionString"].ConnectionString, "System.Data.SqlClient"); 

Jetzt nutzen Ihre Migrationen diese Verbindungszeichenfolge und Ihre Anwendung wird, was Verbindungszeichenfolge Sie in den Konstruktor verwenden.

In Bezug auf Ihren Datenbankinitialisierer verwende ich normalerweise nicht die MigrateDatabaseToLatestVersion, aber ich glaube, dass sie tun wird, was Sie brauchen, ohne etwas anzupassen.

Als Nebenbemerkung, wenn Sie die Live-Umgebung der Web App kontrollieren, ist es sicherer, die SQL-Skripte aus den Migrationen zu generieren und sie manuell auf Ihre Live-DB anzuwenden. Auf diese Weise können Sie die generierten Skripts optimieren. Dies ist besonders interessant, wenn Sie umfangreiche Änderungen an vorhandenen Tabellen mit Daten vornehmen müssen.

Verwandte Themen