EF - 而在HTTP请求的模型正在创建例外上下文不能使用 [英] EF - The context cannot be used while the model is being created exception during HTTP requests

查看:300
本文介绍了EF - 而在HTTP请求的模型正在创建例外上下文不能使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到是被创建的模型,而该上下文不能使用。问题在我的网页我的一个Web应用程序。这种特殊的网页发送到服务器每2-3秒刷新屏幕。从我的测试中,我发现,如果我有2个或以上的浏览器实例中打开此页面,几分钟后,我收到在仓库中的异常由深了,而该模型正在创建上下文无法使用。

I am receiving "The context cannot be used while the model is being created." issue in my web application in one of my webpages. This particular webpage POSTs to the server every 2-3 seconds to refresh the screen. From my testing I found that If I have 2 or more browser instances open to this page, after several minutes I receive a "The context cannot be used while the model is being created" exception from deep in the repository.

这code所谓的服务来获取所需的数据。这code在MVC控制器类的自定义授权属性执行。

This code calls a "service" to retrieve the needed data. This code is executed in an custom authorization attribute of the MVC Controller class.

// Code in custom "Authorization" attribute on the controller
int? stationId = stationCookieValue;  // Read value from cookie
RoomStationModel roomStationModel = RoomStationService.GetRoomStation(stationId); // Error occurs inside this call

下面是RoomStationModel

Here is the "RoomStationModel"

public class RoomStationModel
{
    [Key]
    public int RoomStationId { get; set; }

    public int? RoomId { get; set; }
    [ForeignKey("RoomId")]
    public virtual RoomModel Room { get; set; }
    /* Some other data properties.... */
 }

public class RoomModel
{
    [Key]
    public int RoomId { get; set; }

    public virtual ICollection<RoomStationModel> Stations { get; set; }
}

下面是code上面的服务电话:

Here is the code for the service call above:

public RoomStationModel GetRoomStation(int? roomStationId)
{
    RoomStationModel roomStationModel = null;
    if (roomStationId.HasValue)
    {
        using (IRepository<RoomStationModel> roomStationRepo = new Repository<RoomStationModel>(Context))
        {
            roomStationModel = roomStationRepo.FirstOrDefault(rs => rs.RoomStationId == roomStationId.Value, false, new string[] { "Room" });
        }
    }

    return roomStationModel;
}

下面是库​​....出错位置

Here's the repository....where the error occurs

    public class Repository<TObject> : IRepository<TObject> where TObject : class
    {
        protected MyContext Context = null;

        public Repository(IDataContext context)
        {
            Context = context as MyContext;
        }

        protected DbSet<TObject> DbSet { get { return Context.Set<TObject>(); } }

    public virtual TObject FirstOrDefault(Expression<Func<TObject, bool>> predicate, bool track = true, string[] children = null)
    {
        var objectSet = DbSet.AsQueryable();

        if (children != null)
            foreach (string child in children)
                objectSet = objectSet.Include(child);

        if (track)
            return objectSet.Where(predicate).FirstOrDefault<TObject>(predicate);

        return objectSet.Where(predicate).AsNoTracking().FirstOrDefault<TObject>(predicate);
    }
}

错误的屏幕截图:

Screenshot of error:

堆栈跟踪

  at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
   at System.Data.Entity.Internal.InternalContext.Initialize()
   at System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType(Type entityType)
   at System.Data.Entity.Internal.Linq.InternalSet`1.Initialize()
   at System.Data.Entity.Internal.Linq.InternalSet`1.Include(String path)
   at System.Data.Entity.Infrastructure.DbQuery`1.Include(String path)
   at System.Data.Entity.DbExtensions.Include[T](IQueryable`1 source, String path)
   at Vanguard.AssetManager.Data.Repository`1.FirstOrDefault(Expression`1 predicate, Boolean track, String[] children) in C:\Work\VanguardAssetManager\Main\Vanguard.AssetManager.Data\Repository.cs:line 100
   at Vanguard.AssetManager.Services.Business.RoomStationService.GetRoomStation(Nullable`1 roomStationId) in C:\Work\VanguardAssetManager\Main\Vanguard.AssetManager.Services\Business\RoomStationService.cs:line 61
   at Vanguard.AssetManager.Web.Attributes.RoomStationAuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) in C:\Work\VanguardAssetManager\Main\Vanguard.AssetManager.Web\Attributes\RoomStationAuthorizeAttribute.cs:line 52
   at System.Web.Mvc.ControllerActionInvoker.InvokeAuthorizationFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor)
   at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)

EF版本:4.1(code第一)

EF Version: 4.1 (Code first)

推荐答案

您库是短暂的(你创建它每次调用 GetRoomStation(),但实际背景似乎是长期存在的( RoomServiceStation.Context 属性),这意味着你的Web应用程序每次调用将使用相同​​的上下文。

Your repository is short-lived (you create it for each call to GetRoomStation() but your actual context appears to be long-lived (RoomServiceStation.Context property). This means that every call to your web application is going to use the same context.

这是EF在N层场景,你想保持在一个Web应用程序的体系结构模型无国籍状态的东西左右(上下文)。所有这些请求都被引导到在不同的线程相同的背景和你得到的竞争条件。

This is the "EF in an N-tier" scenario where you're trying to keep something stateful around (the context) in the architecturally stateless model of a web application. All those requests are being channeled to the same context on different threads and you're getting a race condition.

一个线程可以开球上下文的第一次初始化响应于请求,另一个进来试图使用的上下文。第二个请求认为的背景下就可以使用了,你会得到这个异​​常。你甚至可以得到这个,如果你有多个上下文试图旋在同一时间的建议<一href=\"http://stackoverflow.com/questions/6099781/how-can-i-$p$pvent-ef-the-context-cannot-be-used-while-the-model-is-being-create?rq=1\">in另一个线程SO 。

One thread could be kicking off first-time initialization of your context in response to a request, and another comes in attempting to use the context. The second request thinks the context is ready for use and you get this exception. You may even get this if you have multiple contexts trying to "spin up" at the same time as suggested in another SO thread.

您可以做几件事情。你可以尝试悲观锁周围访问您的上下文,但你在不必要的瓶颈推杆。你可以尝试建立某种客户正在叫我之前,初始化上下文code,但你必须找到一个好地方要做到这一点,或许用蛮力的方法<一href=\"http://social.msdn.microsoft.com/Forums/en-AU/adodotnetentityframework/thread/18c993be-c357-4c99-908e-f879f28c5ee0\">suggested在MSDN线程。

You can do a few things. You could try pessimistic locking around access to your context, but you're putting in an unnecessary bottleneck. You could try creating some sort of "before clients are calling me, initialize the context" code, but you have to find a good place to do this, perhaps using the "brute force" method suggested in an MSDN thread.

一个更好的事情是简单地创建一个新的上下文的每个的请求,后端服务。有一些开销,是的,但微乎其微。开销大概是不太可能杀人比悲观锁的性能,并且不会受到应用程序池回收事件向外扩展的Web应用程序在一个农场等。

A better thing to do is to simply create a new context for every request to your back-end service. There is some overhead, yes, but minimal. The overhead is probably less likely to kill performance than pessimistic locking, and won't be subject to app pool recycle events scaling out your web app on a farm and so on.

如果你依靠更改跟踪或上下文的其他状态特性,你将失去这项福利。在这种情况下,你将不得不拿出一个不同的机制,以跟踪和减少数据库命中。

If you're relying on change tracking or other stateful nature of a context, you will lose this benefit. In this case, you're going to have to come up with a different mechanism for tracking and minimizing database hits.

MSDN文章这是总结了(重点煤矿):

From an MSDN article this is summed up (emphasis mine):

如果您从一个层到另一个序列化实体,推荐
  模式是为足以保持周围环境的层中期才能长
  对于单个服务方法调用。
后续调用将旋转了一个新的
  上下文的实例来完成每项任务。

If you serialize entities from one tier to another, the recommended pattern is to keep the context around on the mid-tier only long enough for a single service method call. Subsequent calls will spin up a new instance of the context to complete each task.

<一个href=\"http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/46811556-f8e7-450a-9b59-c885e702abc3\">A在EF / WCF / N层的线程也可以给你一些启发和豪尔赫的的博客文章#5 EF左右的N-层级会谈(全系列可能是一个良好的阅读)。顺便说一句,我碰到同样的事情:很多客户打的情况下在同一时间,导致这个问题。

A thread on EF/WCF/N-tier may also give you some insights, and Jorge's blog post #5 talks about EF in N-Tiers (the whole series might be a good read). And by the way, I've run into the exact same thing: many clients hitting the context at the same time, resulting in this issue.

这篇关于EF - 而在HTTP请求的模型正在创建例外上下文不能使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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