自动保存带有UnitOfWork模式的DBContext

时间:2015-07-05 12:07:37

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

因此,在MVC中使用UnitOfWork模式我不希望每次修改对象时都要调用unitOfWork保存方法。通常使用UnitOfWork,您可以执行以下操作:

    if (ModelState.IsValid)
    {
        var user = new User()
        {
            Id = Guid.NewGuid(),
            Username = model.Username,
            Email = model.Email,
            Password = model.HashedPassword()
        };
        unitOfWork.UserRepository.Insert(user);
        unitOfWork.Save();
    }

我想删除“unitOfWork.Save();”并且只知道每次操作完成时它都会保存。所以我在我的UnitOfWork的Dispose方法中添加了一个save子句:

    protected virtual void Dispose(bool disposing)
    {
        if (context.ChangeTracker.HasChanges())
        {
            context.SaveChangesAsync();
        }
        if (!this.isDisposed)
        {
            if (disposing)
            {
                context.Dispose();
            }
        }
        this.isDisposed = true;
    }

当然,我的控制器会调用dispose:

    protected override void Dispose(bool disposing)
    {
        unitOfWork.Dispose();
        base.Dispose(disposing);
    }

我确信HasChanges()方法按预期工作并且调用了SaveChangesAsync(),但这不起作用。我认为它可能与SaveChangesAsync创建的线程没有完成有关,因为它所依赖的对象被处理掉了?

但如果是这种情况,则SaveChangesAsync必定是危险的,因为即使您在控制器操作中使用它,它也可以将事务锁定几秒钟,并发现上下文在有机会保存之前已被处理掉。

那么我做错了什么?我似乎无法找到一种既定的方法,但我无法想象每个使用工作单元模式的人都必须记住每次修改任何对象时都要手动调用Save方法。

3 个答案:

答案 0 :(得分:2)

虽然我同意使用Dispose()保存更改是一个坏主意,但事情不起作用的原因是因为Dispose() 不是异步方法。因此,直接调用context.SaveChangesAsync()后跟context.Dispose()可能会处理上下文,而异步处理仍在进行或尚未在后台启动。

您至少应切换到SaveChanges()

答案 1 :(得分:1)

作为另一种可能性,既然你声明你想要自动保存每个动作,你可以在结束请求时在这里进行保存:

MVC End Request

执行此操作的模式(以某种方式)实际上称为

  

每个请求的工作单元

你可以在网上找到更多关于它的细节,它适用于一些网络应用程序(尽管有很多变化)

答案 2 :(得分:0)

将多个操作一起调用SaveChanges()(意味着只调用一次)具有许多优势,但并非每个应用程序都需要这些优势。如果您在某处有基本存储库类,为什么不使用添加/删除/更新操作来定义它,其中每个操作都会调用SaveChanges()?

类似的东西:

public abstract RepositoryBase<T>
{
    public void Add(T entity)
    {
        context.Add(entity);
        context.SaveChanges();
    }

    public void Remove(T entity)
    {
        context.Remove(entity);
        context.SaveChanges();
    }

    etc...
}

使用Dispose保存更改我发现非常糟糕 IMO。

注意此变更后工作单位的作用: 它唯一的角色是作为上下文的包装器,确保所有存储库共享相同的上下文,但其最初的主要责任将消失。