我正在与另一位开发人员讨论是否在我们的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();
}
}
我看到的大多数示例都使用第二种模式。一种模式比另一种更“正确”吗?
每次更改后保存,将避免保存大量实体。在某些图形结构中,这可能是一个正确性问题,而在其他情况下,这只会导致CPU负载增加。 SaveChanges
的成本不仅是写作,而且是遍历加载到上下文中的实体。
为什么要反对实体框架?做,它要做什么:保存批次并在对实体进行所有更改后最后调用SaveChanges
。
PersistCustomer
方法的名称错误:它保留了所有内容,而不仅仅是客户。您不能使用EF保留单个实体。您的抽象(存储库)已损坏。
人们通常将EF包装在通用存储库中,该存储库不添加任何功能,但删除了功能。这对我来说从来没有道理。
我倾向于支持第二种方法。
第一个可能会“隐藏”保存操作,并且对用户会更好看,但不要忘记您正在失去对保存操作的控制。如果您发现自己更新了多个实体,这将导致多个单独更改的开销,而不是让它们立即执行-这意味着需要更多执行时间。
虽然它可能感觉像是多余地调用了“ SaveChanges”,但是第二种方法将允许您一次保存多个更改=无开销。
我发现通过消除不必要的提高性能的能力来限制自己。
我移至第一种方法有两个原因:
1]有时(不经常)我忘记调用SaveChanges()
方法。例如,当我不得不同时提交一个事务(或者我保存了更改但忘记提交一个事务)并且我不理想的测试没有捕获到这种错误时(类似于您不调用Validate()
的方法)每次您更改业务实体中的某项功能时都会起作用,因为您可以忘记调用它(即使这不是唯一原因))。
2)可以在内存存储库中转换存储库接口(用于测试目的),并且没有意义调用SaveChanges()
,这可能会造成混淆,因为标准集合没有这种方法,并且应该隐藏实现给用户。
如果需要添加集合,则可以向存储库Import(List<Customer> customers)
添加另一个方法,然后执行foreach
并调用SaveChanges()
。对于用户来说也很清楚,存在一些优化的方法。
如果我需要在多个存储库上执行多项操作,则可以通过事务包装所有操作(可以在关系数据库中锁定所有微小的更改,以避免不一致或死锁,直到未整体提交事务为止。]]
但是我认为第一种或第二种方法没有更好的选择,两者都需要权衡取舍,这可能是个人喜好问题?