使用 DI 但获取:一个实体对象不能被 IEntityChangeTracker 的多个实例引用,但是
本文关键字:IEntityChangeTracker 不能 但是 引用 实例 对象 实体 获取 DI 一个 使用 | 更新日期: 2023-09-27 18:22:20
我审查过的关于这个主题的问题都没有使用 IOC,而我是这样我不明白为什么我会收到此错误。据我了解,如果我只有一个上下文实例,我不应该收到此错误。这是我设置的分解版本。
我正在尝试运行这个:
var product = new Product();
product.ShortText = "something";
foreach (var category in _categoryService.Get().Take(5).ToList())
product.Categories.Add(category);
_productService.Update(product);
_productService.SaveChanges();
我的_productService
:
public class ProductService : IProductService
{
private readonly IRepository<Product> _productRepository;
public ProductService(IRepository<Product> productRepository)
{
_productRepository = productRepository;
}
//Code removed for brevity
}
_categoryService
几乎与_productService
相同。
IRepository
是这样的:
public class EfRepository<T> : IRepository<T> where T : BaseEntity
{
private readonly IDbContext _context;
private IDbSet<T> _entities;
public EfRepository(IDbContext context)
{
_context = context;
}
protected virtual IDbSet<T> Entities
{
get { return _entities ?? (_entities = _context.Set<T>()); }
}
public IQueryable<T> Table
{
get { return Entities; }
}
public void Update(T entity)
{
Entities.AddOrUpdate(m => m.Id, entity);
}
}
我正在为每个请求注册我的上下文,如下所示:
builder.RegisterType<CcDataContext>().As<IDbContext>().InstancePerRequest();
记住这一点,我看待它的方式,_productService
和_categoryService
应该具有相同的上下文实例,所以我对为什么会出现错误感到困惑。
编辑
这是我的背景:
public class CcDataContext : DbContext, IDbContext
{
static CcDataContext()
{
Database.SetInitializer<CcDataContext>(null);
}
public CcDataContext()
: base("CcDataContext") //String.Format("Name={0}", CcConfig.Get("ConnectionStringName")))
{
}
public DbSet<Website> Websites { get; set; }
public DbSet<Store> Stores { get; set; }
public DbSet<StoreView> StoreViews { get; set; }
public DbSet<Customer> Customers { get; set; }
public DbSet<CustomerAddress> CustomerAddresses { get; set; }
public DbSet<CustomerContact> CustomerContacts { get; set; }
public DbSet<CustomerRole> CustomerRoles { get; set; }
public DbSet<RolePermission> PermissionRoles { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Category> Categories { get; set; }
public IDbSet<T> Set<T>() where T : BaseEntity
{
return base.Set<T>();
}
}
这与 DI 容器没有任何关系。该错误意味着您在上下文中的某个位置创建了两个都指向同一实体的DbSet
属性。
自从 ASP.NET Identity 出现以来,最常见的原因是个人尝试添加自己的DbSet<ApplicationUser>
属性,而IdentityDbContext<ApplicationUser>
已经有一个属性,应用程序的上下文继承了该属性。
不确定这是否是您的问题,因为您尚未指定正在使用的 MVC 版本或发布上下文的内容。不过,这应该足以让您研究这个问题。
我已经找到了原因。这是我在_categoryService
上执行的缓存。我的Get()
方法如下所示:
public IEnumerable<Category> Get()
{
return _cacheManager.Get(CcCacheCategoryAll, () => (_categoryRepository.Table.AsEnumerable()));
}
基本上,因为我没有将我的实体与缓存时它们的上下文分离,所以我会在以后的请求中获取缓存的版本,并且它们没有相同的上下文。因此,尽管不是 DI 出了问题,但这是因为实体之间的上下文不匹配。