EF代码第一迁移错误“对象已经断开或不存在于服务器” [英] EF code first migration error "Object has been disconnected or does not exist at the server"

查看:198
本文介绍了EF代码第一迁移错误“对象已经断开或不存在于服务器”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在SQL Server 2008上使用Entity Framework 6.1.1,并且我有一个长时间运行的代码首次迁移(约20分钟)。它会得到结果,然后给出以下错误。

  System.Runtime.Remoting.RemotingException:Object'/ f10901d8_94fe_4db4_bb9d_51cd19292b01 / bq6vk4vkuz5tkri2x8nwhsln_106 .rem'已被断开或不存在于服务器。 
在System.Data.Entity.Migrations.Design.ToolingFacade.ToolLogger.Verbose(String sql)
在System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.ExecuteSql(DbTransaction事务,MigrationStatement migrationStatement,DbInterceptionContext interceptionContext)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements,DbTransaction事务,DbInterceptionContext interceptionContext)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatementsInternal(IEnumerable`1 migrationStatements,DbConnection连接)
在System.Data.Entity.Migrations.DbMigrator。c__DisplayClass30。< ExecuteStatements> b__2e()
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy。<   c__DisplayClass1。< Execute> b.o()
在System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute [TResult](Func`1操作)
在System.Data.Entity.SqlServer.DefaultSqlExecut ionStrategy.Execute(Action操作)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable`1 migrationStatements,DbTransaction existingTransaction)
在System.Data.Entity.Migrations.DbMigrator.ExecuteStatements(IEnumerable `1 migrationStatements)
在System.Data.Entity.Migrations.Infrastructure.MigratorBase.ExecuteStatements(IEnumerable`1 migrationStatements)
在System.Data.Entity.Migrations.DbMigrator.ExecuteOperations(String migrationId,XDocument targetModel ,IEnumerable`1操作,IEnumerable`1 systemOperations,Boolean downgrading,Boolean auto)
在System.Data.Entity.Migrations.DbMigrator.ApplyMigration(DbMigration migration,DbMigration lastMigration)
在System.Data.Entity .Migrations.Infrastructure.MigratorLoggingDecorator.ApplyMigration(DbMigration migration,DbMigration lastMigration)
在System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations,String targetMigrationId,String lastMigrationId)
在System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations,String targetMigrationId,String lastMigrationId)
在System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String在System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)中,更新> b__b()
在System.Data.Entity.Migrations.DbMigrator中的


在System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
在System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
在System.Data .Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
在System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
在System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
在System.AppDomain.DoCallBack(CrossApp DomainDelegate callBackDelegate)
在System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
在System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration,Boolean force)
在System.Data.Entity.Migrations.UpdateDatabaseCommand。  c__DisplayClass2。< .ctor> b__0()
在System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action命令)

迁移的要点是更新数据库中存储某些二进制数据的MIME类型的字段。它遍历每一行,读取二进制数据,尝试确定它是什么样的内容,然后将相应的MIME类型值写入该行。



脚本下面使用ADO.NET生成要运行的更新语句的列表。我使用ADO.NET,因为我必须使用.NET的映像库(System.Drawing.Imaging.ImageFormat)来确定每行中的二进制内容的类型(它将是jpeg,png或pdf)。

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

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

//读取每个记录,并根据存储的数据类型更新内容类型值
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(updateStatements中的string updateStatement)
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(异常)
{
/ * PDF文档将抛出异常,因为它们不是图像,但您可以检查它是否真的是一个PDF
* by检查前四个字节将为0x25 0x50 0x44 0x46(%PDF)。 * /
if(document [0] == 0x25&&& document [1] == 0x50&& document [2] == 0x44&& document [3] == 0x46)
返回PDF;
else
返回NULL;
}

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

返回NULL;
}

我看过这个五年前的帖子及其链接的文章似乎不已经存在了至少我找不到他们。



有没有人知道这里发生了什么?



- 更新 -

这似乎与迁移需要多长时间运行有关。我创建了一个迁移,绝对没有别的睡眠22分钟

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

我收到相同的错误。所以这似乎是一个超时的事情。我不是100%他们所指的服务器上的对象,我在这个问题上找不到很多关于代码首次迁移的问题。



我试过将$ code> CommandTimeout 属性设置为迁移 Configuration.cs 文件到5000,但没有帮助。我还尝试将SQL Server的删除查询超时设置设置为0以防止任何超时,但它也没有帮助。

解决方案

这一直使我们头痛。这个问题似乎是由于EF迁移实用程序的设计。该程序创建一个新的AppDomain来运行迁移。新的AppDomain的日志记录在原始的AppDomain中处理(这就是为什么涉及到远程处理)。显然,如果个人迁移需要太多时间,记录器就会被GC.我已经通过用Console.WriteLine替换所有的日志记录来验证这一点,这使问题消失了。可能会修改migrate.exe工具(但可能需要更改EntityFramework程序集本身)。


I am using Entity Framework 6.1.1 on SQL Server 2008 and I have a long running code first migration (about 20 minutes). It gets to the end and then gives the following error.

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)

The point of the migration is to update a field in the database that stores the MIME type of some binary data. It loops through every row, reads the binary data, attempts to determine what kind of content it is, then writes the appropriate MIME type value into the that row.

The script below uses ADO.NET to generate a list of update statements to run. I use ADO.NET because I must use .NET's imaging libraries (System.Drawing.Imaging.ImageFormat) to determine the type of binary content in each row (it'll be a jpeg, png, or 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;
}

I've seen this five year old post and the articles that it links to do not seem to exist anymore. At least I can't find them.

Does anyone know what's going on here?

-- UPDATE --
This appears to have something to do with how long the migration takes to run. I created a migration that does absolutely nothing other than sleep for 22 minutes

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

and I got the same error. So it appears to be a timeout thing. I'm not 100% what object on the server they are referring to and I can't find much on this issue as it relates to code first migrations.

I tried setting the CommandTimeout property in the migrations Configuration.cs file to 5000 but it didn't help. I also attempted to set the SQL Server's Remove query timeout setting to 0 to prevent any timeouts but it didn't help either.

解决方案

This has been causing us headaches. The problem appears to be due to the design of the EF migration utility. The program creates a new AppDomain in which to run migrations. The logging for the new AppDomain is handled in the original AppDomain (which is why remoting gets involved). Apparently the logger gets GC'ed if an individual migration takes too much time. I've verified this by replacing all the logger calls with Console.WriteLine - which makes the problem go away. There may be a fix by altering the migrate.exe tool (but may possibly require altering EntityFramework assembly itself).

这篇关于EF代码第一迁移错误“对象已经断开或不存在于服务器”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆