2015-06-23 14 views
8

Sto utilizzando Entity Framework 6.1.1 su SQL Server 2008 e ho una prima migrazione del codice in esecuzione (circa 20 minuti). Arriva alla fine e poi dà il seguente errore.Errore di migrazione del primo codice EF "L'oggetto è stato disconnesso o non esiste sul server"

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) 

Il punto della migrazione è per aggiornare un campo nel database che memorizza il tipo MIME di alcuni dati binari. Passa attraverso ogni riga, legge i dati binari, tenta di determinare che tipo di contenuto è, quindi scrive il valore del tipo MIME appropriato nella riga corrispondente.

Lo script seguente utilizza ADO.NET per generare un elenco di istruzioni di aggiornamento da eseguire. Io uso ADO.NET perché devo usare le librerie di imaging di .NET (System.Drawing.Imaging.ImageFormat) per determinare il tipo di contenuto binario in ogni riga (sarà jpeg, png o pdf).

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; 
} 

Ho visto this five year old post e gli articoli che si collega a non sembrano esistere più. Almeno non riesco a trovarli.

Qualcuno sa cosa sta succedendo qui?

- AGGIORNAMENTO -
Questo sembra avere qualcosa a che fare con quanto tempo la migrazione necessario per eseguire. Ho creato una migrazione che non fa assolutamente altro che dormire per 22 minuti

public override void Up() 
{ 
    System.Threading.Thread.Sleep(1320000); 
} 

e ho ottenuto lo stesso errore. Quindi sembra essere una cosa del timeout. Non sono al 100% l'oggetto sul server a cui si riferiscono e non riesco a trovare molto su questo problema in quanto si riferisce alle migrazioni prima del codice.

Ho provato a impostare la proprietà CommandTimeout nel file di migrazione Configuration.cs su 5000 ma non è stato di aiuto. Ho anche tentato di impostare l'impostazione Remove query timeout di SQL Server su 0 per impedire qualsiasi timeout, ma non è stata di aiuto neanche.

+0

Sì, probabilmente qualcosa timeout correlati. Vorrei cercare di eseguire quelle migrazioni esterne, se possibile. http://stackoverflow.com/questions/18900204/errors-during-code-first-add-migration –

+0

Potrei farlo ma non è un'opzione interessante perché quindi non posso semplicemente eseguire le migrazioni su qualsiasi database per ottenere aggiornato. Devo ricordare di eseguire questo altro script manualmente in aggiunta. Voglio dire se questo è quello che succede allora penso che lo farò, ma sembra piuttosto stupido doverlo fare. – d512

+0

Forse guardate a spostare quel codice nel metodo Seed Application Initializer(). if (! upToDate) {fare l'aggiornamento}. –

risposta

-1

Questo ci ha causato mal di testa. Il problema sembra essere dovuto alla progettazione dell'utilità di migrazione EF. Il programma crea un nuovo AppDomain in cui eseguire le migrazioni. La registrazione per il nuovo AppDomain viene gestita nell'AppDomain originale (motivo per cui il remoting è coinvolto). Apparentemente il logger ottiene GC 'se una migrazione individuale richiede troppo tempo. Ho verificato questo sostituendo tutte le chiamate del registratore con Console.WriteLine - il che fa sparire il problema. Potrebbe esserci una correzione modificando lo strumento migrate.exe (ma potrebbe essere necessario modificare lo stesso assembly EntityFramework).

3

in camicia da [GitHub EntityFramework 6 Issue # 96] [https://github.com/aspnet/EntityFramework6/issues/96#issuecomment-289782427]

Il problema è che il contratto di locazione di vita ToolLogger (classe base MigrationsLogger è un MarshalByRefObject) è al (5 minuti) default. ToolingFacade crea il logger, che risiede nel dominio dell'app del programma principale . Le migrazioni vengono eseguite in un dominio diverso per l'app . Se una migrazione richiede più di 5 minuti, il tentativo di registrare qualsiasi ulteriore informazione provoca questo errore. Una soluzione potrebbe essere quella di aumentare la durata del lease nel programma principale. Così...nel programma principale , prima di creare il ToolingFacade, impostare la durata di locazione per un periodo di tempo più lungo:

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

Un piccolo suggerimento: Metti questo nel tuo file di migrazione dal questo per l'intero dominio dell'app. Ciò assicurerà che sia utilizzato solo durante l'applicazione di una nuova migrazione. – Cataklysim

Problemi correlati