【问题标题】:Will Entity Framework fail when running on a high volumn IIS web site实体框架在大容量 IIS 网站上运行时会失败吗
【发布时间】:2012-06-20 10:15:59
【问题描述】:

我们一直在尝试分析这个异常:

消息:错误:对象引用未设置为对象的实例。 堆栈跟踪:在 System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) 在 System.RuntimeType.CreateInstanceSlow(布尔 publicOnly,布尔 skipCheckThis,布尔型填充缓存)在 System.RuntimeType.CreateInstanceDefaultCtor(布尔 publicOnly, 布尔型 skipVisibilityChecks,布尔型 skipCheckThis,布尔型 fillCache) 在 System.Activator.CreateInstanceT 在 Z.Services.ObjectContextManagement.ScopedObjectContextManager1.get_ObjectContext() at Z.Services.DatabaseAccess.DatabaseAccess2.Manage() 在 Z.Services.DatabaseAccess.DatabaseAccess`2.get_ObjectContext()

基本上我们在获取 ObjectContext 时会出错。

从这个问题:Entity Framework lazy loading doesn't work from other thread 我们看到 EF 依赖于保持在同一个线程上。

从这个 Jon Skeet 对这个问题的回答:Will a request in IIS run on a single thread? 我们看到 IIS 具有线程敏捷性。

当流量较低时,我们看不到此错误,但当负载增加时,我们会看到此错误。

所以问题是:如果 EF 依赖于保持在单个线程上,并且 IIS 不会将请求保持在单个线程上,那么 EF 可以在部署在 IIS 上的应用程序上使用吗?

编辑

var frameworkAssembly = Assembly.GetAssembly(typeof(ObjectContextManager<>));
var managerType = frameworkAssembly.GetType(managerTypeName + "`1", true, true);
managerType = managerType.MakeGenericType(typeof(TObjectContext));
ObjectContextManager = Activator.CreateInstance(managerType) as ObjectContextManager<TObjectContext>;

似乎错误发生在上述代码的最后一行。该错误仅发生在重负载下的生产中。

编辑 2

ObjectContextManager 继承自 ObjectContext,它是一个 EF 类。

 public abstract class ObjectContextManager<T> where T : ObjectContext

【问题讨论】:

  • 鉴于 EF IS 部署在很多网站上都没有问题,你应该检查一下你做错了什么。你能显示有问题的代码吗?
  • @PanagiotisKanavos 感谢您的评论,我已经更新了问题
  • 这不是 EF 代码。这是关于 Activator 未能创建类型。你确定 managerType 不为空吗?顺便说一句,什么是 ObjectContextManager?你为什么要创建这样的课程?为什么不直接将上下文类型作为类型参数传递?
  • 我不明白这个“线程敏捷性”是什么意思。我需要关心吗?我希望 IIS 必须管理此类线程更改,而无需我对任何同步进行编程。可怕,如果你的问题真的是由 IIS 基础设施引起的......
  • EF 不是线程安全的,这意味着您不能在多个线程中使用相同的 ObjectContext 实例(或其他常见的 EF 对象,如 ObjectStateManager 等)。但是,如果您为每个线程创建一个单独的 ObjectContext 实例,那么您应该没问题。正如之前有人在您的堆栈跟踪和您的示例中指出的那样,您正在使用任何属于 EF 的东西。

标签: c# multithreading entity-framework iis objectcontext


【解决方案1】:

我最近在线程敏捷性和 IIS 方面遇到了一些问题。 IIS 可以在请求的线程通过管道时转移它。这并不意味着您必须更加了解并发性。重要的是上下文数据附加到线程的方式。

在 ASP.NET 环境中,此存储是通过 HttpContent.Current 变量完成的,该变量包含当前线程上正在处理的当前请求的详细信息。它通过System.Runtime.Remoting.Messaging.CallContext.HostContext 变量来实现。

许多为每个线程保留数据的解决方案都使用ThreadStatic 属性,但是由于线程切换,这在 ASP 环境中会失败。线程静态一开始是有价值的,然后在处理管道的中途似乎变成了null

ASP.NET 将跟踪 HttpContextCurrentPrincipal 以及可能的语言环境。 CallContext 数据和存储在ThreadStatic 变量中的数据不会被复制。

虽然很烦人,但答案是改变策略并使用HttpContext.Current.Items 而不是CallContext 或线程静态。

在您的情况下,检查 EF 使用的策略,并查看实现是否可插入。

正如 Jon Skeet 所指出的,更多信息可在 Cup(Of T) 上获得,但更多地将其用作您的发现的启动板,而不是其本身的目的。

【讨论】:

    猜你喜欢
    • 2011-05-14
    • 2011-08-24
    • 1970-01-01
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-29
    相关资源
    最近更新 更多