【发布时间】:2012-02-21 18:25:39
【问题描述】:
我们的代码中有一个场景,即只允许更改实体的少数属性。为了保证这一点,我们有类似这样的代码:
public void SaveCustomer(Customer customer)
{
var originalCustomer = dbContext.GetCustomerById(customer.Id);
if (customer.Name != originalCustomer.Name)
{
throw new Exception("Customer name may not be changed.");
}
originalCustomer.Address = customer.Address;
originalCustomer.City = customer.City;
dbContext.SaveChanges();
}
这段代码的问题是对dbContext.GetCustomerById 的调用并不总是给我一个Customer 类的新实例。如果客户已经从数据库中获取,Entity Framework 会将实例保存在内存中,并在每次后续调用时返回它。
这将我们引向实际问题 - customer 和 originalCustomer 可能指的是同一个实例。在这种情况下,customer.Name 将等于 originalCustomer.Name,我们将无法检测它是否与数据库不同。
我猜大多数其他 ORM 也存在同样的问题,因为 identitymap 设计模式。
有什么办法可以解决这个问题吗?我可以以某种方式强制 EF 始终为我提供客户类的新实例吗?
或者我们应该重构代码吗?有谁知道这种场景有什么好的设计模式?
【问题讨论】:
-
GetCustomerById来自哪里?另外,你的上下文的生命周期是多少? -
啊,对不起。 GetCustomerById 只是 DbSet
.Find() 的包装方法。生命周期是每个 HTTP 请求的。 -
如果您不想更改
Name,则不允许上层代码与Customer实体一起使用(= 创建新类,其中Name将是只读的)或隐藏二传手。
标签: entity-framework orm identity-map