长生活实体框架环境 - 避免数据完整性问题的最佳做法 [英] Long living Entity Framework context - best practice to avoid data integrity issues

查看:101
本文介绍了长生活实体框架环境 - 避免数据完整性问题的最佳做法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为一个非常基本的情况,我们来进行这两个操作:

As a very rudimentary scenario, let's take these two operations:

UserManager.UpdateFirstName(int userId, string firstName)
{
    User user = userRepository.GetById(userId);
    user.FirstName = firstName;
    userRepository.SaveChanges();
}

InventoryManager.InsertOrder(Order newOrder)
{
    orderRepository.Add(newOrder);
    orderRepository.SaveChanges();
}

我仅在网络项目中使用了EF,并严重依赖于无状态网络。随着每一个请求,我将获得注入到我的业务层外观对象(服务,管理器,无论你想要调用它们)的上下文的全新副本,所有业务经理共享同一个EF上下文实例。目前,我正在开发一个WPF项目,我正在注入业务经理,随后将它们直接用于View Model中的存储库。

I have only used EF in web projects and relied heavily on the stateless nature of the web. With every request I would get a fresh copy of the context injected into my business layer facade objects (services, managers, whatever you want to call them), all of the business managers sharing the same instance of the EF context. Currently I am working on a WPF project and I'm injecting the business managers and subsequently the repositories that they use directly into the View Model.

我们假设用户正在一个复杂的屏幕和他的第一个按钮单击调用UpdateFirstName()方法。我们假设SaveChanges()由于任何原因而失败。他们的第二个按钮点击将调用InsertOrder()方法。

Let's assume a user is on a complicated screen and his first button click calls the UpdateFirstName() method. Let's assume SaveChanges() fails for whatever reason. Their second button click will invoke the InsertOrder() method.

在网络上这不是一个问题,因为操作#2的上下文不相关(新的http请求)到操作#1使用的上下文。然而在桌面上,这两个动作都是相同的上下文。该问题出现在用户的名字已经被修改并且被上下文跟踪的事实上。即使原来的SaveChanges()没有使用(比如db当时不可用),调用SaveChanges()的第二个操作不仅会插入新的命令,还会更新用户的名字。在几乎每一个原因这是不可取的,因为用户早就忘记了他们的第一个动作,无论如何失败。

On the web this is not an issue as the context for operation #2 is not related (new http request) to the context used by operation #1. On the desktop however, it's the same context across both actions. The issue arises in the fact that the user's first name has been modified and as such is tracked by the context. Even though the original SaveChanges() didn't take (say the db was not available at that time), the second operation calling SaveChanges() will not only insert the new order, it will also update the users first name. In just about every cause this is not desirable, as the user has long forgotten about their first action which failed anyway.

这显然是一个愚蠢的例子,但我总是往往会碰到这种情况,我希望我可以开始新鲜的每个用户操作的新上下文,而不是有更长的寿命(例如WPF窗口的生活)上下文。

This is obviously being a silly example, but I always tend to bump into these sort of scenarios where I wish I could just start fresh with a new context for every user action as opposed having a longer lived (for the life of the WPF window for example) context.

你们如何处理这些情况?

How do you guys handle these situations?

推荐答案

来自ad hoc的非常真实的询问桌面应用程序直接攻击数据库。

A very real interrogqation when coming from ad hoc desktop apps that hit the database directly.

与ORMs的理念相似的答案是具有与屏幕相同的使用寿命的上下文。
数据上下文是一个工作单元的实现。对于一个网络应用程序来说,这显然是这个请求,它的效果很好。

The answer that seems to go with the philosophy for ORMs is to have a context that has the same lifespan as your screen's. The data context is a Unit Of Work implementation, in essence. For a web app, it is obviously the request and it works well.

对于桌面应用程序,你可以将一个上下文绑定到屏幕上,或者可能绑定到编辑操作(加载和按保存)。只读操作可能会有一个丢弃的上下文(使用ID在必要时重新加载对象,例如在网格中按删除按钮时)。
如果您想要保持其他用户的修改,关闭整个应用程序生命周期的上下文(关系集合在首次加载时将被缓存)。
还要忘记直接在不同的窗口之间共享EF实体,因为这样做有效地使它成为一个应用程序,从而使其成为一个长寿命的上下文。

For a desktop app, you could have a context tied to the screen, or possibly tied to the edit operation (between loading and pressing "save"). Read only operations could have a throwaway context (using IDs to reload the object when necessary, for example when pressing a "delete button" in a grid). Forget about a context that spans the entire application's life if you want to stay aware of modifications from other users (relationship collections are cached when first loaded). Also forget about directly sharing EF entities between different windows, because that effectively makes it an app-wide and thus long lived context.

在我看来,ORM由于这一点,往往会在桌面应用程序上执行网络式设计。没有真正的方式,我害怕。
这不是一件必要的事情本身。通常不要在桌面级别攻击数据库,如果要在多个实例之间共享。在这种情况下,您将使用服务层,EF将在其元素中,您的问题将转移到服务上下文...

It seems to me ORMs tend to enforce a web-like design on desktop apps because of this. No real way around this I'm afraid. Not that it is necessary a bad thing in itself. You should normally not be attacking the database at the desktop level if it is to be shared between multiple instances. In which case you would be using a service layer, EF would be in its element and your problem would be shifted to the "service context"...

这篇关于长生活实体框架环境 - 避免数据完整性问题的最佳做法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆