Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 无法完成该操作,因为DbContext已被释放-LifeStylePerwcfoOperation_Entity Framework_Dependency Injection_Castle Windsor_Dbcontext_Unit Of Work - Fatal编程技术网

Entity framework 无法完成该操作,因为DbContext已被释放-LifeStylePerwcfoOperation

Entity framework 无法完成该操作,因为DbContext已被释放-LifeStylePerwcfoOperation,entity-framework,dependency-injection,castle-windsor,dbcontext,unit-of-work,Entity Framework,Dependency Injection,Castle Windsor,Dbcontext,Unit Of Work,我有一个WCF Web服务,目前遇到一些并发性问题。目前负荷较小,但预计在未来几天内将大幅增加 总体设置是WCF、实体框架6、依赖项注入(Castle Windsor)、UnitOfWork&Repository模式 我设置了一个并行访问服务的压力测试,我可以重新创建并发错误,例如 提交数据库事务时报告了错误,但无法确定该事务在数据库服务器上是成功还是失败 已成功提交对数据库的更改,但更新对象上下文时出错。ObjectContext可能处于不一致的状态。内部异常消息:AcceptChanges

我有一个WCF Web服务,目前遇到一些并发性问题。目前负荷较小,但预计在未来几天内将大幅增加

总体设置是WCF、实体框架6、依赖项注入(Castle Windsor)、UnitOfWork&Repository模式

我设置了一个并行访问服务的压力测试,我可以重新创建并发错误,例如

  • 提交数据库事务时报告了错误,但无法确定该事务在数据库服务器上是成功还是失败
  • 已成功提交对数据库的更改,但更新对象上下文时出错。ObjectContext可能处于不一致的状态。内部异常消息:AcceptChanges无法继续,因为对象的键值与ObjectStateManager中的另一个对象冲突。在调用AcceptChanges之前,请确保键值是唯一的

  • 属性“ID”是对象密钥信息的一部分,无法修改

从我所做的研究来看,我似乎应该给我的DbContext注入一种生活方式的操作。目前,这项工作正在以短暂的生活方式进行

当我切换到Lifestyle PerwcfoOperation并重新运行测试时,我每次都会得到以下结果:

  • 无法完成该操作,因为DbContext已被释放
所以我有两个问题:

  • 我的假设正确吗?解决这个问题的真正方法是将我的DbContext转换为lifestyleperwcfooperation
  • 如果是这样的话,那么我的DbContext为什么会被吞噬呢
  • 下面是一些代码:

    AppStart.cs:

    IocContainer.AddFacility<TypedFactoryFacility>();
    
    IocContainer.Register(Component.For<IRepositoryFactory>().AsFactory());
    
    IocContainer.Register(Component.For<IUnitOfWork>()
                                   .ImplementedBy<UnitOfWork>)
                                 /*.LifestylePerWcfOperation()*/);
    
    IocContainer.Register(Component.For(typeof(IDbContext))
                                   .ImplementedBy(dbContextType)
                                   .DependsOn(Dependency.OnValue("connectionString", String.Format(ConfigurationManager.ConnectionStrings["---"].ConnectionString))));
                                 /*.LifestylePerWcfOperation()*/
    
    IocContainer.Register(Component.For(typeof(IRepository<>))
                                   .ImplementedBy(typeof(Repository<>))
                                   .LifestyleTransient()
                                 /*.LifestylePerWcfOperation()*/);
    
    // Register the actual dbContextType so consuming applications can access it without an interface
    IocContainer.Register(Component.For(dbContextType)
                                   .Named(dbContextType.Name)
                                   .DependsOn(Dependency.OnValue("connectionString", String.Format(ConfigurationManager.ConnectionStrings["----"].ConnectionString)));
                                 /*.LifestylePerWcfOperation()*/
    
    Repository.cs

    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly IDbSet<T> _dbset;
    
        public Repository(IDbContext dbContext)
        {
            _dbset = dbContext.Set<T>();
        }
    
        public IQueryable<T> Query()
        {
            return _dbset.AsQueryable();
        }
    
        public virtual IEnumerable<T> GetAll()
        {
            return _dbset.AsEnumerable();
        }
    
        public virtual void Add(T entity)
        {
            _dbset.Add(entity);
        }
    
        public virtual void Delete(T entity)
        {
            _dbset.Remove(entity);
        }
    
        public virtual void Delete(ICollection<T> entities)
        {
            entities.ToList().ForEach(Delete);
        }
    }
    
    公共类存储库:IRepository,其中T:class
    {
    专用只读IDbSet _dbset;
    公共存储库(IDbContext dbContext)
    {
    _dbset=dbContext.Set();
    }
    公共IQueryable查询()
    {
    返回_dbset.AsQueryable();
    }
    公共虚拟IEnumerable GetAll()
    {
    返回_dbset.AsEnumerable();
    }
    公共虚拟空添加(T实体)
    {
    _添加(实体);
    }
    公共虚拟作废删除(T实体)
    {
    _删除(实体);
    }
    公共虚拟作废删除(ICollection实体)
    {
    entities.ToList().ForEach(删除);
    }
    }
    

    如果需要,我可以添加更多代码。谢谢你能提供的任何帮助

    回答您的问题:

    1) 你将生活方式转变为生活方式的做法是正确的

    2) 您正在从UnitOfWork中处理DBContext。DBContext由Windsor注入,因此Windsor将对其调用Dispose。使用windsor时,切勿处置注入的对象,只有在使用factory或Resolve创建对象时,才必须释放(而不是处置)该对象,以便windsor可以处置它

    我希望通过LifeStylePerwcfoOperations和删除Dispose代码,代码应该可以正常运行

    祝你好运,
    Marwijn.

    我能够解决这个问题

    Fix正是Marwijn提到的。修复后,我仍然得到一个类似的错误

    最后的解决办法是接受每一次注册,使其成为一种生活方式。我注册了一些生命周期较短的对象,因此DbContext也开始处理这些对象


    如果有人遇到此错误,并且您正在使用Castle/EF,请不要显式地处置DbContext(让Castle来做),并使一切都成为Lifestyle PerwcfoOperation。这应该可以解决问题。然后返回并有选择地重置您不希望成为lifestyle PerwcfoOperation的任何对象的生活方式,并确保它不会在运行过程中中断。

    您的DBContext注册没有指定生活方式,因此Windsor的默认设置将适用:Singleton。这肯定会引起问题。谢谢Marwijn!这确实是第一步。我还需要对代码进行一些其他更改,但这些更改没有发布在这里
    public class Repository<T> : IRepository<T> where T : class
    {
        private readonly IDbSet<T> _dbset;
    
        public Repository(IDbContext dbContext)
        {
            _dbset = dbContext.Set<T>();
        }
    
        public IQueryable<T> Query()
        {
            return _dbset.AsQueryable();
        }
    
        public virtual IEnumerable<T> GetAll()
        {
            return _dbset.AsEnumerable();
        }
    
        public virtual void Add(T entity)
        {
            _dbset.Add(entity);
        }
    
        public virtual void Delete(T entity)
        {
            _dbset.Remove(entity);
        }
    
        public virtual void Delete(ICollection<T> entities)
        {
            entities.ToList().ForEach(Delete);
        }
    }