为什么在存储库中包含Repo.SaveChanges()方法?

时间:2013-01-17 23:11:48

标签: c# entity-framework repository-pattern

我正在与另一位开发人员讨论是否在我们的Entity Framework 5存储库中公开了repo.SaveChanges()方法。

我们正在考虑拥有一个自动保存此类更改的回购(快速而肮脏的示例):

public class Repo {
    private OurEfContext _context = new OurEfContext();

    public void PersistCustomer(Customer cust)
    {
        // update customer code here
        _context.SaveChanges(); //  <-- is this okay?
    }
}

我们正在考虑的另一个选择是公开一个单独的Repo.PersistChanges()方法,如下所示:

public class Repo {
    private OurEfContext _context = new OurEfContext();

    public void PersistCustomer(Customer cust)
    {
        // update customer code here
        // no call to _context.SaveChanges();
    }

    public void PersistChanges()
    {
        _context.SaveChanges();
    }
}

我见过的大多数例子都使用第二种模式。一种模式比另一种更“正确”吗?

3 个答案:

答案 0 :(得分:8)

每次更改后保存都会阻止您保存批量实体。在某些图形结构中,这可能是正确性问题,在其他情况下,它只会驱动CPU负载。 SaveChanges的成本不仅仅是写作,还包括遍历加载到上下文中的实体。

为什么反对实体框架?做,它想要你做什么:保存批次并在完成对实体的所有更改后最后调用SaveChanges

方法PersistCustomer被错误地命名:它坚持一切,而不仅仅是客户。您无法使用EF保留单个实体。您的抽象(存储库)已损坏。

人们经常将EF包装在通用存储库中,该存储库不添加任何功能但会删除功能。这从来没有对我有意义。

答案 1 :(得分:1)

出于以下两个原因,我移至第一种方法:

1)有时(不经常)我忘记调用SaveChanges()方法。例如,当我不得不同时提交一个事务(或者我保存了更改但忘记提交一个事务)并且我的测试不理想时没有捕获到这种错误(类似于您不叫{{1 }}每次您在业务实体中进行更改时都会起作用,因为您可以忘记调用它(即使这不是唯一原因)。

2)可以将存储库接口转换为内存存储库(出于测试目的),并且没有意义调用Validate(),这可能会造成混淆,因为标准集合没有这种方法和实现应该对用户隐藏。

如果需要添加集合,可以向存储库SaveChanges()添加另一个方法,执行Import(List<Customer> customers),然后调用foreach。对于用户来说也很清楚,存在一些优化的方法。

如果我需要在多个存储库上执行多个操作,则可以通过事务包装所有操作(可以在关系数据库中锁定所有微小的更改,以避免不一致或死锁,直到未整体提交事务为止)。

但是我认为第一种或第二种方法没有更好的选择,两者都需要权衡取舍,这可能是个人喜好问题?

答案 2 :(得分:0)

我倾向于支持第二种方法。

第一个可能会“隐藏”保存操作,并且对用户来说会更好看, 但不要忘记你正在失去对储蓄行动的控制权。 如果您发现自己更新了多个实体,这将导致多个分离的更改的开销,而不是让它们立即执行 - 这意味着更多的执行时间。

虽然可能感觉冗余地调用“SaveChanges”,但第二种方法可以让您一次保存多个更改 =无开销。

我发现通过消除改善作为不必要行为的表现的能力来限制自己。