2015-06-23 3 views
8

Ich verwende Entity Framework 6.1.1 unter SQL Server 2008 und habe eine lange laufende Code-Erstmigration (ca. 20 Minuten). Es kommt zum Ende und gibt dann den folgenden Fehler aus.Fehler bei der ersten Migration des EF-Codes "Objekt wurde getrennt oder ist auf dem Server nicht vorhanden"

System.Runtime.Remoting.RemotingException: Object '/f10901d8_94fe_4db4_bb9d_51cd19292b01/bq6vk4vkuz5tkri2x8nwhsln_106.rem' has been disconnected or does not exist at the server. 
    at System.Data.Entity.Migrations.Design.ToolingFacade.ToolLogger.Verbose(String sql) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction transaction, MigrationStatement migrationStatement, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbTransaction transaction, DbInterceptionContext interceptionContext) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements, DbConnection connection) 
    at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClass30.<ExecuteStatements>b__2e() 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.<>c__DisplayClass1.<Execute>b__0() 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute[TResult](Func`1 operation) 
    at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute(Action operation) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements, DbTransaction existingTransaction) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements) 
    at System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId, XDocument targetModel, IEnumerable`1 operations, IEnumerable`1 systemOperations, Boolean downgrading, Boolean auto) 
    at System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration, DbMigration lastMigration) 
    at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId) 
    at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration) 
    at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b() 
    at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase) 
    at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration) 
    at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run() 
    at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) 
    at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner) 
    at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force) 
    at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0() 
    at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command) 

Der Punkt der Migration ist ein Feld in der Datenbank zu aktualisieren, die den MIME-Typ einiger binären Daten speichert. Es durchläuft jede Zeile, liest die Binärdaten, versucht festzustellen, um welche Art von Inhalt es sich handelt und schreibt dann den entsprechenden MIME-Typ in die entsprechende Zeile.

Das folgende Skript verwendet ADO.NET, um eine Liste der auszuführenden Update-Anweisungen zu generieren. Ich verwende ADO.NET, weil ich die Imaging-Bibliotheken von .NET (System.Drawing.Imaging.ImageFormat) verwenden muss, um den Typ des binären Inhalts in jeder Zeile zu bestimmen (es wird ein JPEG, PNG oder PDF sein).

public override void Up() 
{ 
    List<string> updateStatements = new List<string>(); 

    using(SqlConnection conn = new SqlConnection(ConfigurationManager.AppSettings["ConnectionString"])) 
    { 
     SqlCommand cmd = new SqlCommand("SELECT Table1ID, Image FROM Table1"), conn); 
     conn.Open(); 

     //read each record and update the content type value based on the type of data stored 
     using (SqlDataReader reader = cmd.ExecuteReader()) 
     { 
      while (reader.Read()) 
      { 
       long idValue = Convert.ToInt64(reader["Table1ID"]); 
       byte[] data = (byte[])reader["Image"]; 
       string contentType = GetMimeType(data); 
       updateStatements.Add(string.Format("UPDATE Table1 SET Content_Type = {0} WHERE Table1ID = {1}", contentType, idValue)); 
      } 
     } 
    } 

    foreach (string updateStatement in updateStatements) 
     Sql(updateStatement); 
} 

public string GetMimeType(byte[] document) 
{ 
    if (document != null && document.Length > 0) 
    { 
     ImageFormat format = null; 

     try 
     { 
      MemoryStream ms = new MemoryStream(document); 
      Image img = Image.FromStream(ms); 
      format = img.RawFormat; 
     } 
     catch (Exception) 
     { 
      /* PDF documents will throw exceptions since they aren't images but you can check if it's really a PDF 
      * by inspecting the first four bytes with will be 0x25 0x50 0x44 0x46 ("%PDF"). */ 
      if (document[0] == 0x25 && document[1] == 0x50 && document[2] == 0x44 && document[3] == 0x46) 
       return PDF; 
      else 
       return NULL; 
     } 

     if (format.Equals(ImageFormat.Jpeg)) 
     { 
      return JPG; 
     } 
     else if (format.Equals(System.Drawing.Imaging.ImageFormat.Png)) 
     { 
      return PNG; 
     } 
    } 

    return NULL; 
} 

Ich habe gesehen, this five year old post und die Artikel, die sie Links scheinen nicht mehr existieren. Zumindest kann ich sie nicht finden.

Weiß jemand, was hier vor sich geht?

- UPDATE -
Dies scheint etwas mit dem zu tun zu haben, wie lange die Migration laufen dauert. Ich habe eine Migration erstellt, die absolut nichts anderes tut als 22 Minuten lang schlafen

und ich habe den gleichen Fehler. Es scheint also eine Auszeit zu sein. Ich bin nicht 100% welches Objekt auf dem Server, auf das sie sich beziehen, und ich kann nicht viel zu diesem Thema finden, da es sich um Code-Erstmigrationen handelt.

Ich habe versucht, die CommandTimeout Eigenschaft in den Migrationen Configuration.cs Datei auf 5000, aber es hat nicht geholfen. Ich habe auch versucht, die Remove query timeout Einstellung von SQL Server auf 0 festzulegen, um keine Zeitüberschreitungen zu verhindern, aber es half auch nicht.

+0

Ja, wahrscheinlich etwas im Zusammenhang Timeout. Ich würde versuchen, so weit wie möglich außerhalb der Migrationen zu laufen. http://stackoverflow.com/questions/18900204/errors-during-code-first-add-migration –

+0

Ich könnte das tun, aber es ist nicht so attraktiv eine Option, weil ich dann nicht einfach die Migrationen auf irgendeine Datenbank ausführen kann es auf dem neuesten Stand. Ich muss daran denken, dieses andere Skript zusätzlich manuell auszuführen. Ich meine, wenn es darauf ankommt, dann schätze ich, dass ich es tun werde, aber es scheint ziemlich witzig zu sein, dass ich das tun muss. – d512

+0

Vielleicht sehen Sie sich diesen Code in die Application Initializer Seed() -Methode verschieben. if (! upToDate) {Update durchführen}. –

Antwort

-1

Das hat uns Kopfschmerzen bereitet. Das Problem scheint auf dem Entwurf des EF-Migrationsprogramms zurückzuführen zu sein. Das Programm erstellt eine neue Anwendungsdomäne, in der Migrationen ausgeführt werden. Die Protokollierung für die neue Anwendungsdomäne wird in der ursprünglichen Anwendungsdomäne gehandhabt (weshalb Remoting einbezogen wird). Offensichtlich wird der Logger GC'ed, wenn eine einzelne Migration zu viel Zeit in Anspruch nimmt. Ich habe dies verifiziert, indem ich alle Logger-Aufrufe durch Console.WriteLine ersetzt habe - wodurch das Problem beseitigt wird. Es kann einen Fehler geben, indem Sie das migrate.exe-Tool ändern (möglicherweise müssen Sie jedoch die EntityFramework-Assembly selbst ändern).

3

Pochierte von [GitHub EntityFramework 6 Ausgabe # 96] [https://github.com/aspnet/EntityFramework6/issues/96#issuecomment-289782427]

Das Problem ist, dass die ToolLogger Leasing Lebensdauer (Basisklasse MigrationsLogger ein MarshalByRefObject ist) ist die Standardeinstellung (5 Minuten). Die ToolingFacade erstellt den Logger, der sich in der App-Domäne des Hauptprogramms befindet. Die Migrationen werden in einer anderen App Domäne ausgeführt. Wenn eine Migration länger als 5 Minuten dauert, führt der Versuch, weitere Informationen zu protokollieren zu diesem Fehler. Eine Lösung wäre die Lease-Lebenszeit im Hauptprogramm zu erhöhen. Damit...im Haupt Programm, bevor das ToolingFacade erzeugen, stellen Sie den Mietvertrag Lebensdauer auf einen längeren Zeitraum:

using System.Runtime.Remoting.Lifetime; 
... 
LifetimeServices.LeaseTime = TimeSpan.FromHours(1); 
+2

Ein kleiner Hinweis: Setzen Sie dies in Ihre Migrationsdatei seit dies für die gesamte App-Domain. Dadurch wird sichergestellt, dass es nur beim Anwenden einer neuen Migration verwendet wird. – Cataklysim

Verwandte Themen