【问题标题】:Can't find objects which reference entity framework entity找不到引用实体框架实体的对象
【发布时间】:2014-10-02 01:14:30
【问题描述】:

我遇到了 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 中的属性可能会给我带来麻烦,但我是 Entity Framework 的新手,我不确定。我是否应该采用不同的设计,比如this

【问题讨论】:

    标签: c# asp.net-mvc entity-framework


    【解决方案1】:

    您可能需要考虑一种类似工作单元的方法,其中一个上下文在多个存储库之间共享。这个post 的公认答案就是一个很好的例子。我已经看到了 ContextPerRequest 解决方案,例如您的示例中的解决方案,但我从未对它们感到疯狂。理想情况下,您需要一个短暂的上下文,它可以做一件事,例如添加一张发票和两个发票项目 - 一个工作单元。然后,您可以将整个操作包装在 TransactionScope 中,并将其作为一个单元成功或失败。

    【讨论】:

    • 我通过使用链接解决方案解决了这个问题,谢谢!我从 userManager 中删除了上下文,并在每个请求时简单地创建了 userManager。只是出于好奇,据我了解,所有缓存都是由上下文完成的,您不想因此而尝试持久化它们吗?
    • 这是一个原因,在一个非常长的上下文中,你可以想象数据库中的所有内容都在上下文中的内存中,但是 dbContext 是一个非常轻量级的对象,所以没有理由不在需要时将其启动并在完成后将其丢弃。您可以放心,底层 sql 连接已被释放并释放回池中。我还认为它会让你更多地思考你的代码并更好地构建它,我见过的最慢的 mvc 视图涉及一个 ContextPerRequest 和一个延迟加载的集合,这会导致每个项目的数据库调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-03
    • 1970-01-01
    • 2017-07-28
    • 1970-01-01
    • 2011-07-20
    • 2011-11-26
    • 2011-03-04
    相关资源
    最近更新 更多