我遇到了InvalidOperationException,因为" IEntityChangeTracker的多个实例无法引用实体对象。"在EntityFrameWorkRepository.Create()的第一行。
我知道这是由于拥有多个数据库上下文,但在这种情况下,由于所有数据库访问都通过一个指定对象,其唯一目的是管理数据库上下文,因此代码没有明显的第二个上下文。这是因为所讨论的Web应用程序是相当交互式的,因此用户不断创建必须保存在数据库中的新对象。这导致了先前设计的问题,该设计使用了锁定和单个上下文,因此除了相关方法之外,代码被重构并且有效。
EF课程:
public class EntityFrameWorkRepository<TKey, TEntity> : IDisposable, IRepository<TKey,TEntity> where TEntity: class
{
private readonly IDbContext _context;
private IDbSet<TEntity> _entities;
public EntityFrameWorkRepository()
{
_context = new ApplicationDbContext();
}
private IDbSet<TEntity> Entities
{
get { return _entities ?? (_entities = _context.Set<TEntity>()); }
}
public void Create(TEntity entity)
{
Entities.Add(entity);
_context.SaveChanges();
}
public void Dispose()
{
_context.Dispose();
}
}
用于所有数据库访问的服务对象:
public class Service : IService
{
public const string Persistance = "Persist";
public const int CacheTaskSeconds = 300; //Check every 5 minutes
public const double IdleMinutes = 30.0;
private readonly IKvpRepository<int, SimulationCollection> _simulationCollectionAppStateRepository;
private readonly UserManager<ApplicationUser> _userManager;
public Service(IKvpRepository<int, SimulationCollection> simulationCollectionAppStateRepository)
{
_userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
AddTaskToCache(Persistance, CacheTaskSeconds);
}
public SimulationCollection CreateCollection(Guid userId, string name, string description)
{
using (var _simulationCollectionEFRepository = new EntityFrameWorkRepository<int, SimulationCollectionEntity>())
{
var applicationUser = _userManager.FindById(userId.ToString());
if (applicationUser == null)
throw new ArgumentOutOfRangeException("ApplicationUser matching userId doesn't exist");
var collectionEntity = new SimulationCollectionEntity(applicationUser, name, description);
_simulationCollectionEFRepository.Create(collectionEntity);
return collection;
}
}
}
我试图添加到数据库的对象:
public class SimulationCollectionEntity
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public virtual int Id { get; set; }
public string Name { get; set; }
public virtual ApplicationUser User { get; set; }
public DateTime DateCreated { get; set; }
public string Description { get; set; }
[ForeignKey("SimulationCollectionEntityId")]
public virtual ICollection<SimulationEntity> Simulations { get; set; }
[Obsolete("Only needed for serialization and materialization", true)]
public SimulationCollectionEntity() {}
public SimulationCollectionEntity(ApplicationUser currentUser, string name, string description)
{
User = currentUser;
Name = name;
Description = description;
DateCreated = DateTime.Now;
}
}
是否有一种简单的方法可以查看给定对象可能附加到哪些上下文?我已经检查过collectionEntity是否附加到_userManager,因为它有一个dbContext,但它的状态是分离的。 EF可能会指望我以不同于我的方式添加对象吗?我怀疑SimulationCollectionEntity中的属性可能会给我带来麻烦,但我是实体框架的新手,我不确定。我是否应该采用不同的设计,而不是this?
答案 0 :(得分:1)
您可能希望考虑一种工作单元,例如在多个存储库之间共享一个上下文的方法。这个post的接受答案就是一个很好的例子。我见过类似你的示例中的ContextPerRequest解决方案,但我从未对它们感到疯狂。理想情况下,您需要一个简短的上下文,其中包括添加发票和两个发票项目 - 一个工作单元。然后,您可以将整个操作包装在TransactionScope中,并将其作为一个单元成功或失败。