强制实体框架返回新实例

发布于 2025-01-07 22:59:32 字数 877 浏览 1 评论 0原文

我们的代码中有一个场景,只允许更改实体的少数属性。为了保证这一点,我们有与此类似的代码:

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 类的新实例。如果已经从数据库中获取了客户,实体框架会将实例保留在内存中,并在每次后续调用时返回它。

这给我们带来了实际的问题 - customeroriginalCustomer 可能引用同一个实例。在这种情况下,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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

与之呼应 2025-01-14 22:59:32

您可以尝试从上下文中分离实体,这将删除对上下文的所有引用(以及身份映射行为)。
因此,在将 Customer 传递给您的方法之前,您可以将其分离:

yourContext.Detach(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:

yourContext.Detach(customer);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文