简体   繁体   English

DbContext 已被释放

[英]DbContext has been disposed

I developed a web application with ASP.NET MVC 4 and SQL Server 2008, I create ContextManager class to have only one database context in all pages.我使用 ASP.NET MVC 4 和 SQL Server 2008 开发了一个 web 应用程序,我创建了 ContextManager class 在所有页面中只有一个数据库上下文。

public static class ContextManager
{
    public static HotelContext Current
    {
        get
        {
            var key = "Hotel_" + HttpContext.Current.GetHashCode().ToString("x")
                      + Thread.CurrentContext.ContextID.ToString();
            var context = HttpContext.Current.Items[key] as HotelContext;
            if (context == null)
            {
                context = new HotelContext();
                HttpContext.Current.Items[key] = context;
            }
            return context;
        }
    }
}

It works properly in most of the pages, but in registration page something goes wrong and my context gone deposed with following error:它在大多数页面中都能正常工作,但在注册页面中出现了问题,我的上下文因以下错误而被废除:

The operation cannot be completed because the DbContext has been disposed.操作无法完成,因为 DbContext 已被释放。

public ActionResult Register ( RegisterModel model )
{
    if ( ModelState.IsValid )
    {
        // Attempt to register the user
        try
        {
            WebSecurity.CreateUserAndAccount( model.UserName, model.Password,
                                              new
                                               {
                                                      Email = model.Email,
                                                      IsActive = true,
                                                      Contact_Id = Contact.Unknown.Id
                                               } );

            //Add Contact for this User.
            var contact = new Contact { Firstname = model.FirstName, LastName = model.Lastname };
            _db.Contacts.Add( contact );
            var user = _db.Users.First( u => u.Username == model.UserName );
            user.Contact = contact;
            _db.SaveChanges();
            WebSecurity.Login( model.UserName, model.Password );

at the line _db.Contacts.Add( contact );在行_db.Contacts.Add( contact ); I got the exception.我得到了例外。

But without using ContextManager by changing但是不通过更改使用 ContextManager

HotelContext _db = ContextManager.Current;

into:进入:

HotelContext _db = new HotelContext();

the problem was solved.问题解决了。 But I need to use my own ContextManager.但是我需要使用我自己的 ContextManager。 What is the problem?问题是什么?

Your context has been disposed somewhere else (not in the code you've shown), so basically when you access it from your Register action, it throws the exception. 您的上下文已放置在其他地方(不在您显示的代码中),因此基本上,当您从Register操作访问它时,它将引发异常。

Actually, you shouldn't use a static singleton to access to your context. 实际上,您不应该使用静态单例来访问您的上下文。 Do instantiate a new DbContext instance for each request . 为每个请求实例化一个新的DbContext实例 See c# working with Entity Framework in a multi threaded server 请参阅C#在多线程服务器中使用Entity Framework

In my case, my GetAll method was not calling ToList() method after where clause in lambda expression. 就我而言,我的GetAll方法未在lambda表达式中的where子句之后调用ToList()方法。 After using ToList() my problem was solved. 使用ToList()之后,我的问题解决了。

Where(x => x.IsActive).ToList();

You are probably 'lazy-loading' a navigation property of User in your registration view. 您可能正在注册视图中“延迟加载” User的导航属性。 Make sure you include it by using the Include method on your DbSet before sending it to the view: 在将其发送到视图之前,请确保通过使用DbSet上的Include方法将其Include DbSet

_db.Users.Include(u => u.PropertyToInclude);

Also, sharing DbContext s with a static property may have unexpected side effects. 同样,共享具有静态属性的DbContext可能会有意外的副作用。

I used to have the same problem. 我曾经有过同样的问题。 I solved it doing as it was said above. 我按照上面所说的解决了这个问题。 Instantiate a new instance of your context. 实例化上下文的新实例。

Try using this: 尝试使用此:

            using (HotelContextProductStoreDB = new ProductStoreEntities())
            {
                //your code
            }

This way it'll be created a new instance everytime you use your code and your context will not be disposed. 这样,每次使用代码时都会创建一个新实例,并且不会释放上下文。

Why override the Dispose(bool)? 为什么要覆盖Dispose(bool)?

public partial class HotelContext : DbContext
{
    public bool IsDisposed { get; set; }
    protected override void Dispose(bool disposing)
    {
        IsDisposed = true;
        base.Dispose(disposing);
    }
}

And, then check IsDisposed 然后,检查IsDisposed

public static class ContextManager
{
    public static HotelContext Current
    {
        get
        {
            var key = "Hotel_" + HttpContext.Current.GetHashCode().ToString("x")
                      + Thread.CurrentContext.ContextID.ToString();
            var context = HttpContext.Current.Items[key] as HotelContext;
            if (context == null || context.IsDisposed)
            {
                context = new HotelContext();
                HttpContext.Current.Items[key] = context;
            }
            return context;
        }
    }
}

Maybe, can be an option. 也许可以选择。

If you need to check if your DbContext is still valid to use (not disposed), DbContext needs to be recreated: See answer on defining a IsDisposed() extended method for a DbContext partial class https://stackoverflow.com/a/74894375/1518501如果您需要检查您的 DbContext 是否仍然有效(未处置),则需要重新创建 DbContext:请参阅有关为 DbContext 部分类定义 IsDisposed() 扩展方法的答案https://stackoverflow.com/a/74894375 /1518501

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM