为啥实体框架会在一段时间后忘记我的数据库模型中的内容?

Posted

技术标签:

【中文标题】为啥实体框架会在一段时间后忘记我的数据库模型中的内容?【英文标题】:Why does Entity Framework forget what's in the model for my database after a while?为什么实体框架会在一段时间后忘记我的数据库模型中的内容? 【发布时间】:2016-06-26 19:37:37 【问题描述】:

免责声明/警告:我是 .net 的新手,一年前才开始使用它。

我有一个使用 Entity Framework 5.0、.Net 4.6 和 MVC 4.0 的 MVC webapp,在 Azure 上运行。此应用程序访问两个数据库,它们都带有 EDMX 文件,并且都位于同一 Azure 服务器上。数据库的连接字符串在 web.config 中作为开发连接,但 Azure 应用程序具有覆盖它们的环境连接字符串。

两个 EDMX 文件都是通过“从数据库更新模型”生成的(即,数据库首先存在,然后生成 edmx 以匹配它)。一个 EDMX 文件位于同一解决方案的第二个项目中,该项目是对我的应用程序的引用。 此 EDMX 文件/模型工作正常。第二个 EDMX 文件位于我的应用程序的模型部分,仅代表三个表和少量存储过程。我已经有一年没碰过这个 EDMX 了,在过去的一年里它偶尔会出现间歇性问题,偶尔无法访问数据库,但可以通过重新启动应用程序来解决。

最近,我一直在对 web 应用程序进行更改(但仍然没有更改 EDMX 或访问该数据库模型的视图/控制器),现在该应用程序无法频繁访问数据库。当我重新启动,或更改连接字符串时,它会重新开始工作,但一个小时左右后忘记了数据库。

感觉 webapp 不知何故失去了与数据库的连接。连接字符串好,模型准确等(因为它在应用重新启动时起作用)。

为什么这种情况发生在一个数据库而不是另一个数据库上?我能做些什么来修复它?我不能只是每小时都重新启动应用程序。

这是我目前收到的两条错误消息:

当我尝试拉回名为 [Database] 的表(EF 在模型中将其称为 Databas)中的记录时

Message: [InvalidOperationException: The entity type Databas is not part of the model for the current context.]
 System.Data.Entity.Internal.InternalContext.UpdateEntitySetMappingsForType(Type entityType):59
 System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType):13
 System.Data.Entity.Internal.Linq.InternalSet`1.Initialize():0
 System.Data.Entity.Internal.Linq.InternalSet`1.Include(String path):0
 System.Data.Entity.Infrastructure.DbQuery`1.Include(String path):21
 CVSupportPortal.Models.ViewModels.CloudAdminViewModel..ctor(Firm f):482
 CVSupportPortal.Areas.CVS.Controllers.FirmsController.Cloud(Int32 firmid):206
 (unknown).lambda_method(Closure , ControllerBase , Object[] ):-1
 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters):129
 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters):0
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41():0
 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult):0
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass37+<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33():30
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult):0
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass25+<>c__DisplayClass2a.<BeginInvokeAction>b__20():23
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult):0

当我调用存储过程时:

Message: [InvalidOperationException: The type parameter 'CVSupportPortal.Models.EF.Database_Status_List_Result' in ExecuteFunction is incompatible with the type 'CloudDatabasesModel.Database_Status_List_Result' returned by the function. ]
 System.Data.Common.Utils.MetadataHelper.CheckFunctionImportReturnType[TElement](EdmType expectedEdmType, MetadataWorkspace workspace):46
 System.Data.Common.Utils.MetadataHelper.GetAndCheckFunctionImportReturnType[TElement](EdmFunction functionImport, Int32 resultSetIndex, MetadataWorkspace workspace):25
 System.Data.Objects.ObjectContext.ExecuteFunction[TElement](String functionName, MergeOption mergeOption, ObjectParameter[] parameters):0
 CVSupportPortal.Models.EF.CloudDatabasesEntities.Database_Status_List():0
(unknown).lambda_method(Closure , ControllerBase , Object[] ):-1
 System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters):129
 System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters):0
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass42.<BeginInvokeSynchronousActionMethod>b__41():0
 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult):0
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass37+<>c__DisplayClass39.<BeginInvokeActionMethodWithFilters>b__33():30
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass4f.<InvokeActionMethodFilterAsynchronously>b__49():134
 System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethodWithFilters(IAsyncResult asyncResult):0
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass25+<>c__DisplayClass2a.<BeginInvokeAction>b__20():23
 System.Web.Mvc.Async.AsyncControllerActionInvoker+<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult):0

【问题讨论】:

你一直在说“忘记数据库”之类的话。这是什么意思?您是否有特定的错误消息、异常类型和/或类似的具体内容?我们需要更具体的信息来帮助您。通常,您看到的情况不应该发生,但可能有很多不同的原因(连接未关闭和达到池限制等)。我们只是需要更多细节,拜托。 对不起...这令人困惑。我现在将错误消息添加到主要问题中。 这听起来可能很傻,但是您可以创建一个单元测试来创建第一个上下文的实例,然后创建第二个上下文的实例,然后对您的第一个表中的每个表执行查询上下文,然后是第二个上下文中的每个表,然后从第一个反转查询的顺序,然后与第二个相同?您可能会遇到实体框架运行时中的一些限制,但很少见,例如,实体名称必须是唯一的。我这里有一个例子:gist.github.com/anonymous/58d979ae22bc1165eb26 感谢您的回复。表/存储的过程名称都是唯一的。太奇怪了。 Web 应用程序当前因这些错误而中断,但我可以通过 Management Studio 很好地连接到数据库。我还可以通过刷新连接字符串来使 Web 应用程序正常工作。我目前正在寻找一种方法来捕获错误并强制刷新连接,看看是否可行。 【参考方案1】:

我仍然不知道问题的原因是什么,但我猜测 Entity Framework 以某种方式失去了与数据库的连接,因为其他位置可以访问数据库,只是在它有之后不能通过 Entity Framework跑了一段时间。我发现 DbContext 类有一个构造函数,允许您在实例化时指定一个连接字符串。我的解决方案是尝试使用它,希望它能启动与数据库的新连接,而不是尝试使用旧连接。

成功了。自从我开始使用它以来,我没有任何中断。这是我更改的内容(我的数据库称为 CloudDatabases)。

CloudDatabases.Context.cs

// Already present
public CloudDatabasesEntities()
    : base("name=CloudDatabasesEntities")



// Added this constructor
public CloudDatabasesEntities(string connStr)
    : base(connStr)


在我需要实例化与数据库的连接的类中:

// Old, normal way
var cdb = new CloudDatabaseEntitites();

// New, non-breaking way
var connStr = ConfigurationManager.ConnectionStrings["CloudDatabasesEntities"].ConnectionString.ToString();
var cdb = new CloudDatabaseEntitites(connStr);

我的 Web.config(或 Azure 环境变量)有一个这样定义的连接字符串:

// Web.config
<add name="CloudDatabasesEntities" connectionString="metadata=res://*/CloudDatabases.csdl|res://*/CloudDatabases.ssdl|res://*/CloudDatabases.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=████████████████████████████████;initial catalog=CloudDatabases;persist security info=True;user id=████████████;password=██████████████████████;multipleactiveresultsets=True;application name=EntityFramework&quot;" providerName="System.Data.EntityClient" />

【讨论】:

以上是关于为啥实体框架会在一段时间后忘记我的数据库模型中的内容?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 spring-boot 和 postgres 连接会在一段时间后断开?

为啥托管在 Windows 服务内的 WCF 服务会在一段时间后死掉

我的领域文件会在一段时间后自动清除所有数据

为啥我们应该让帐户激活/密码重置链接在一段时间后过期?

labview停止循环为啥波形会清除一次

Chromecast 视频播放会在一段时间后永远挂起