ObjectContext未处理

时间:2016-04-13 19:26:34

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

我在Entity Framework 6中遇到了一个问题,其中一直抛出异常。在大多数情况下,应用程序完全正常,直到我尝试通过链接表将用户添加到角色。

抛出的错误如下:

  

无法定义两个对象之间的关系,因为它们附加到不同的ObjectContext对象。

该功能很乐意将用户虚拟地添加到角色中,但只要SaveChanges()被调用,该过程就会失效。

我知道上述错误的原因和原因以及经过一些研究之后,由于上下文没有被正确处理。因此,继续并查看DbContext设置后,我意识到IDisposable没有添加到配置中。不幸的是,无论我在应用程序中的任何一点尝试合并IDisposable仍然没有正确处理上下文。

因此,在花了相当多的时间并且没有通过谷歌运气之后,我想知道你们中是否有人有解决方案或能够指出我正确的方向。

以下是我实施的数据层类的缩减版本:

public class GenericRepository<T> : WebsiteContext, IGenericRepository<T> where T : class
{
    public virtual void Commit()
    {
        SaveChanges();
    }

    public virtual void Delete(int id)
    {
        var record = Set<T>().Find(id);
        if (record == null)
            throw new Exception("Some Message");

        Set<T>().Remove(record);
    }

    // ... ETC
}

public interface IGenericRepository<T> where T : class
{
    void Commit();
    // ... ETC
}

public class WebsiteContext : DbContext, IWebsiteContext
{
    static WebsiteContext()
    {
        Database.SetInitializer<WebsiteContext>(null);
    }

    public WebsiteContext() : base("Name=WebsiteContext") { }

    public IDbSet<User> Users { get; set; }
    // ... ETC

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // ... ETC
    }
}

此实现基于以下Stackoverflow问题。

Entity Framework 6 Code First - Is Repository Implementation a Good One?

以下是导致此问题的Service Layer类和方法的精简版本。

    private IGenericRepository<User> _userRepository;
    private IGenericRepository<ApplicationUserSetting> _userSettingRepository;
    private IGenericRepository<ApplicationRole> _roleRepository;

    public UserManagementService()
    {
        _userRepository = new GenericRepository<User>();
        _roleRepository = new GenericRepository<ApplicationRole>();
        _userSettingRepository = new GenericRepository<ApplicationUserSetting>();
    }

    public void AssignUserRole(AssignRoleModel model)
    {
        var user = _userRepository.GetById(model.UserId);

        if (user == null)
            return;

        var role = _roleRepository.GetById(model.RoleId);

        if (role == null)
            return;

        user.Roles.Add(role);
        _userRepository.Commit();
    }

3 个答案:

答案 0 :(得分:1)

问题与错误状态一样,是因为您有多个DbContext类型的实例为您提取实体。然后,每个获取的实体与检索它的DbContext实例相关联。如果要保留对这些实体的更改,则必须在与其关联的DbContext实例上进行更改,或者必须将其附加到与之无关的DbContext实例。

如果您想保持简单,我建议您实施像AutoFac这样的DI框架。然后,您可以为每个请求创建一个DbContext实例,并将其注入您需要的任何位置。它将允许您保留现有结构(我不会对此进行评论,因为我认为这超出了此问题的范围),最终结果是每个注入GenericRepository instance有一个注入WebsiteContext实例,但WebsiteContext实例是共享的(所有相同的实例)。这样做的好处不再是错误,但缺点是你必须要注意,任何实体的任何更改都会导致这些更改在您执行Save功能后立即保留。

答案 1 :(得分:0)

使用多个存储库会导致此问题。只需使用一个存储库(=一个数据库上下文),并使用不同的方法获取各个类型。

E.g。 _repository.Get(ID)

答案 2 :(得分:0)

超出范围指出您当前的实施方式如何工作,但如果您确实想要使用多个上下文,您可以尽管其他人有说。

如果这样做,您必须先从上一个上下文detach the entity开始。