2014-09-18 66 views
0

我对这个问题的评论没有任何问题使用IOC,而我是这样,我不明白为什么我得到这个错误。据我了解,如果我只有一个我的背景实例,我不应该收到此错误。这是我的设置的细分版本。使用DI,但得到:一个实体对象不能被IEntityChangeTracker的多个实例引用,但

我试图运行这个命令:

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>(); 
    } 
} 

回答

0

我找到了原因。这是我在_categoryService上执行的缓存。我Get()方法是这样的:

public IEnumerable<Category> Get() 
{ 
    return _cacheManager.Get(CcCacheCategoryAll,() => (_categoryRepository.Table.AsEnumerable())); 
} 

基本上,因为我没有从他们时,他们被缓存在上下文脱离我的实体,然后我得到的缓存版本在以后的请求,他们没有相同的上下文。所以虽然它不是DI的错,但是因为上下文在实体之间不匹配。

0

这不会有什么与你的DI容器。该错误意味着在您的上下文中某处,您创建了两个指向同一个实体的DbSet属性。

自从ASP.NET身份出现以来,最常见的原因是个人试图添加属于自己的DbSet<ApplicationUser>属性,而IdentityDbContext<ApplicationUser>已经有一个,您的应用程序的上下文继承了它。

不确定这是否是您的问题,因为您尚未指定您正在使用的MVC版本或发布了上下文的内容。不过,这应该足以让你了解这个问题。

+0

噢,你说的对,在这种情况下,我把重点放在了错误的事情上。我会跳进来看看发生了什么事。我正在使用MVC5。 – webnoob 2014-09-18 21:00:36

+0

我已经用我的上下文类更新了我的OP。我不使用'IdentityDbContext',因为我使用的是自定义身份验证而不是ASP.NET身份。基于你的回答,我已经查找了可能会声明多个“DBSet ”的事件,但找不到任何。 – webnoob 2014-09-18 21:39:00

相关问题