4

我正在使用以下UnitOfWork类,以便通过使用泛型获取我的实体的存储库。

public class UnitOfWork : IUnitOfWork
{
  private readonly EfDbContext _context;

  public UnitOfWork()
  {
    _context = new EfDbContext();
  }

  public IRepository<T> RepositoryFor<T>() where T : Entity
  {
    return new Repository<T>(_context);
  }

  public void Save()
  {
    _context.SaveChanges();
  }
}

但是,我遇到了一些问题,我有两个单独的类为单个实体独立地实例化 UnitOfWork,这意味着为该实体创建了两个存储库。当我尝试保存实体时, 这会导致实体框架抛出“一个实体对象不能被多个 IEntityChangeTracker 实例引用”错误的问题。

我认为我需要更密切地遵循Tom Dykstra在“创建工作单元类”部分下的这篇文章中描述的 UOW 模式,其中存储库存储在私有字段中,如果存在则重用,如果为空则创建。我遇到的问题是我希望我的 UOW 继续使用泛型 -Repository<T>而不必为我在代码中拥有的所有实体类型声明私有存储库字段。

我如何能够存储给定类型的存储库已经实例化的事实并重新使用它而不是创建它的新实例?

---编辑:这是修复---

使用 Ninject,我调整了我的绑定,通过指定仅实例化存储库和 UOW 的单个实例InRequestScope

kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>)).InRequestScope();
//kernel.Bind<IUnitOfWork>().To<UnitOfWork>().InRequestScope(); // Removed based on comment below
kernel.Bind(typeof(EfDbContext)).ToSelf().InRequestScope();
4

2 回答 2

3

问题不在多个存储库中,而是在多个DbContext实例中。EF 告诉您不能一次将同一个实体实例添加到多个上下文中。因此共享存储库无济于事。此外,拥有多个 UoW 共享单例存储库是通往地狱的道路。处理并发(EF 不是线程安全的)、状态等将非常困难。

要解决此问题,您应该执行以下任一操作:

  1. 共享工作单元,以便您DbContext在单个业务操作中使用相同的 UoW(和)实例
  2. 在将实体实例添加到另一个 UoW 之前创建它们的副本。

选择取决于您的具体情况。

于 2012-04-18T04:02:20.500 回答
0

你觉得这个解决方案怎么样?

public class UnitOfWork
    {
        private IRepository<Animal> _animalRepository;
        public IRepository<Animal> Animals => _animalRepository ??= new Repository<Animal>();

        public IRepository<T> Repository<T>()
        {
            var result = GetType()
                .GetProperties()
                .FirstOrDefault(r => typeof(IRepository<T>) == r.PropertyType)?
                .GetValue(this, null);

            return (IRepository<T>)result;
        }
    }
于 2021-02-28T18:07:05.820 回答