【问题标题】:Dbcontext has been disposed when using "using Statement"使用“使用语句”时已释放 Dbcontext
【发布时间】:2014-12-31 02:20:00
【问题描述】:

错误信息:

操作无法完成,因为 dbcontext 已被释放。

有人可以解释我的DbContext 在我执行更新时为什么以及在哪里被处理?

上下文文件:

using System.Data.Entity;

namespace OnlineTest
{
   internal class OnlineTestContext : DbContext
   {
       private OnlineTestContext() : base("name=OnlineTest")
       {
       }

       private static OnlineTestContext _instance;

       public static OnlineTestContext GetInstance
       {
           get
           {
                if (_instance == null)
                {
                    _instance = new OnlineTestContext();
                }
                return _instance;
           }
       }

       public DbSet<User> Users { get; set; }
   }
}

业务逻辑:

    public int UpdateUser(User user)
    {
        user.ModifiedOn = DateTime.Now;

        using (var context = OnlineTestContext.GetInstance)
        {
            context.Entry(user).State = EntityState.Modified;
            return context.SaveChanges();
        }
    }

    public User GetUserByEmailId(string emailId)
    {
        using (var context = OnlineTestContext.GetInstance)
        {
            return context.Users.First(u => u.EmailId == emailId);
        }
    }

单元测试:

    [TestMethod]
    public void UpdateUserUnitTest()
    {
        User user = onlineTestBusinessLogic.GetUserByEmailId("test@test");
        user.PhoneNumber = "+91 1234567890";
        int changes = onlineTestBusinessLogic.UpdateUser(user);
        User Modifieduser = onlineTestBusinessLogic.GetUserByEmailId("test@test");
        Assert.AreEqual(Modifieduser.PhoneNumber, "+91 0987654321");
    }

谢谢。

【问题讨论】:

  • 放弃单身,你的生活会轻松很多

标签: c# entity-framework


【解决方案1】:

它在您第二次调用存储库上的方法时被释放。时间线是这样的:

  1. GetUserByEmailId被调用,_instance为null,所以初始化了
  2. GetUserByEmailId 完成,上下文被释放。但该对象仍然存在于_instance 字段中
  3. UpdateUser 被调用,_instance 不为空,所以在using 中返回旧的上下文
  4. context.SaveChanges 被调用,但是由于这个上下文对象已经被释放,所以抛出异常

这通常是避免像这样缓存数据库上下文的好主意。基本的经验法则是“每个工作单元一个上下文对象”。您可以在 thread(由 Jon Skeet 主演!)中找到更多关于为什么会这样的信息。

【讨论】:

    【解决方案2】:

    using 关键字是您专门说的“当范围关闭时,在我传入的对象上调用 .Dispose()”。这不是您想要的,因为您想一遍又一遍地重用该对象。

    删除使用,您将不再遇到此问题。例如

    var context = OnlineTestContext.GetInstance;
    context.Entry(user).State = EntityState.Modified;
    return context.SaveChanges();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-05-27
      • 1970-01-01
      • 2012-01-19
      • 1970-01-01
      • 2019-01-08
      • 2013-05-12
      • 2011-12-11
      相关资源
      最近更新 更多