强制实体框架返回新实例
我们的代码中有一个场景,只允许更改实体的少数属性。为了保证这一点,我们有与此类似的代码:
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 类的新实例。如果已经从数据库中获取了客户,实体框架会将实例保留在内存中,并在每次后续调用时返回它。
这给我们带来了实际的问题 - customer
和 originalCustomer
可能引用同一个实例。在这种情况下,customer.Name
将等于 originalCustomer.Name
,我们将无法检测它是否与数据库不同。
我猜想大多数其他 ORM 也存在同样的问题,因为 Identitymap 设计模式。
有什么想法可以解决这个问题吗?我可以以某种方式强制 EF 始终为我提供客户类的新实例吗?
或者我们应该重构代码?有谁知道这种情况有什么好的设计模式吗?
We have a scenario in our code when only a few properties of an entity are allowed to be changed. To guarantee that, we have code similar to this:
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();
}
The problem with this code is that the call to dbContext.GetCustomerById
does not always gives me a new instance of the Customer
class. If the customer already has been fetched from the database, Entity Framework will keep the instance in memory and return it on every subsequent call.
This leads us to the actual problem - customer
and originalCustomer
may refer to the same instance. In that case, customer.Name
will be equal to originalCustomer.Name
and we will not be able to detect if it differs from the database.
I guess the same problem exists with most other ORMs as well, because of the identitymap design pattern.
Any ideas how this can be solved? Can I somehow force EF to always give me a new instance of the customer class?
Or should we refactor the code instead? Does anyone know of any good design patterns for this scenario?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可以尝试从上下文中分离实体,这将删除对上下文的所有引用(以及身份映射行为)。
因此,在将 Customer 传递给您的方法之前,您可以将其分离:
you can try by detaching the entity from the context, this will remove all the references to the context (as well as the identitymap behaviour).
So, before passing the Customer to your method you can detach it: