无法使用实体框架更新记录并使用存储库模式进行 ninject

Posted

技术标签:

【中文标题】无法使用实体框架更新记录并使用存储库模式进行 ninject【英文标题】:Can't update a record using entity framework and ninject with Repository pattern 【发布时间】:2011-08-17 15:27:04 【问题描述】:

我正在使用 MVC3、Ninject、Ninject MVC 扩展、EF 4.1

我已经实现了以下 repo 模式。

Repository.cs

public interface IRepository<T> where T : class

    IQueryable<T> AsQueryable();

    IEnumerable<T> GetAll();
    IEnumerable<T> Find(Expression<Func<T, bool>> where);
    T Single(Expression<Func<T, bool>> where);
    T First(Expression<Func<T, bool>> where);

    void Delete(T entity);
    void Add(T entity);
    void Attach(T entity);


public class Repository<T> : IRepository<T> where T : class

    IObjectSet<T> _objectSet;


    public Repository(IObjectContext objectContext)
    

        _objectSet = objectContext.CreateObjectSet<T>();
        //_objectSet.MergeOption = MergeOption.NoTracking;
    

    public IQueryable<T> AsQueryable()
    
        return _objectSet;
    

    public IEnumerable<T> GetAll()
    
        return _objectSet.ToList();
    

    public IEnumerable<T> Find(Expression<Func<T, bool>> where)
    
        return _objectSet.Where(where);
    

    public T Single(Expression<Func<T, bool>> where)
    
        return _objectSet.Single(where);
    

    public T First(Expression<Func<T, bool>> where)
    
        return _objectSet.First(where);
    

    public void Delete(T entity)
    

        _objectSet.DeleteObject(entity);
    

    public void Add(T entity)
    
        _objectSet.AddObject(entity);
    

    public void Attach(T entity)
    


        _objectSet.Attach(entity);

    

工作单元.cs

 public interface IUnitOfWork

    void Commit();


public class UnitOfWork : IUnitOfWork, IDisposable

    private readonly IObjectContext _objectContext;

    public UnitOfWork(IObjectContext objectContext)
    
        _objectContext = objectContext;
    

    public void Dispose()
    
        if (_objectContext != null)
        
            _objectContext.Dispose();
        
        GC.SuppressFinalize(this);
    

    public void Commit()
    
        _objectContext.SaveChanges();
    

ObjectContext.cs

public interface IObjectContext : IDisposable

    IObjectSet<T> CreateObjectSet<T>() where T : class;
    void SaveChanges();


public class ObjectContextAdapter : IObjectContext

    readonly ObjectContext _context;

    public ObjectContextAdapter(ObjectContext context)
    
        _context = context;

    

    public void Dispose()
    
        _context.Dispose();
    

    public IObjectSet<T> CreateObjectSet<T>() where T : class
    

        return _context.CreateObjectSet<T>();
    

    public void SaveChanges()
    
        _context.SaveChanges();
    

我已经使用 Ninject 通过以下实现将它们绑定到 IOC 中

 public override void Load()
    
        Bind(typeof(IRepository<>)).To(typeof(Repository<>));

        Bind<IObjectContext>().To<ObjectContextAdapter>().WithConstructorArgument("context", new MGTContainer());
        Bind<IUnitOfWork>().To<UnitOfWork>();

    

回购模式取自这里 Repo Pattern Implementation

这是控制器中模式的示例使用

 eventRepository.Attach(model);
        unitOfWork.Commit();

插入、读取和删除记录一切正常,但是当我调用附件时出现以下错误

ObjectStateManager 中已存在具有相同键的对象。 ObjectStateManager 无法跟踪具有相同键的多个对象。

我尝试将绑定更改为 InRequestScope,但这会导致后续错误。

提前感谢您的帮助

【问题讨论】:

你能显示引发异常的完整代码吗?创建上下文,调用AttachSaveChanges 不会导致此类异常。 上下文是在 IOC 绑定中创建的,我已经包含了对 attach 方法的调用和随后将调用 submitchanges 方法的 unitof work 提交调用。不知道你还需要什么。 什么是model,它来自哪里?仔细阅读异常:它讨论了 ObjectStateManager 中的 多个 对象。具有相同键的至少第二个对象来自哪里?您的代码根本只显示一个名为 model 的对象。另一个问题可能是您的上下文在 Web 请求后没有得到处理。然后来自早期请求的旧对象(具有相同的键!)可能仍然在上下文中,导致异常。 InRequestScope 听起来确实适合网络应用程序。您确定不需要使用此绑定吗? 嗨 Slauma,model 是从 html 表单的 post 方法传回的 Event 对象的实例。如果您熟悉它,它由 MVC 绑定作为 Event 对象提供。我不知道第二个对象来自哪里,我怀疑问题在于我在 IOC 中绑定上下文的方式。希望有帮助 您可以使用var list = context.ChangeTracker.Entries().ToList();检查上下文中是否有对象。如果您在发布操作开始时调用它,则此列表应始终为空,对于第一个请求以及所有后续请求。我怀疑第二个和以后的请求的列表不是空的,这意味着您的上下文在请求后不会被处理。我对Ninject不熟悉,所以无法详细回答。尝试找出如何为DbContext 正确设置InRequestScope 生命周期。我认为有解决办法。 【参考方案1】:

附加效果不佳。我正在做的只是

    获取单条记录 将所有属性复制到该记录并 提交。

【讨论】:

以上是关于无法使用实体框架更新记录并使用存储库模式进行 ninject的主要内容,如果未能解决你的问题,请参考以下文章

多对多实体框架和存储库模式插入/更新

DAL 中的实体框架存储库模式,如何实现更新功能?

领域模型和实体框架之间的存储库模式和映射

如何在具有存储库模式的实体框架中伪造 DbContext.Entry 方法

实体框架使用 Codefirst、通用存储库、工作单元模式保存多对多关系

实体框架:部分更新记录不起作用