8

我使用 ASP.NET MVC 4 和 SQL Server 2008 开发了一个 Web 应用程序,我创建了 ContextManager 类以在所有页面中只有一个数据库上下文。

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;
        }
    }
}

它在大多数页面中都可以正常工作,但是在注册页面中出现了问题,并且我的上下文因以下错误而被废止:

操作无法完成,因为 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 );

在这条线上_db.Contacts.Add( contact );我得到了例外。

但不通过更改使用 ContextManager

HotelContext _db = ContextManager.Current;

进入:

HotelContext _db = new HotelContext();

问题解决了。但我需要使用自己的 ContextManager。问题是什么?

4

5 回答 5

13

您的上下文已被放置在其他地方(不在您显示的代码中),因此基本上当您从Register操作访问它时,它会引发异常。

实际上,您不应该使用静态单例来访问您的上下文。为每个请求实例化一个新DbContext实例。请参阅c# 在多线程服务器中使用实体框架

于 2013-09-05T11:52:52.513 回答
6

就我而言,我的 GetAll 方法没有在 lambda 表达式中的 where 子句之后调用 ToList() 方法。使用 ToList() 后,我的问题解决了。

Where(x => x.IsActive).ToList();
于 2017-09-18T04:22:35.910 回答
3

您可能正在“延迟加载”User注册视图中的导航属性。确保在将其发送到视图之前使用Include您的方法包含它:DbSet

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

此外,与静态属性共享DbContexts 可能会产生意想不到的副作用。

于 2013-09-05T11:53:45.730 回答
2

我曾经有同样的问题。我按照上面所说的那样解决了它。实例化您的上下文的新实例。

尝试使用这个:

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

这样,每次您使用代码时都会创建一个新实例,并且不会释放您的上下文。

于 2018-02-06T18:57:17.647 回答
2

为什么要覆盖 Dispose(bool)?

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

然后检查 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;
        }
    }
}

也许,可以是一种选择。

于 2019-10-23T01:15:41.420 回答