Frage

I have entity classes that have an integer property (named ROW_VERSION) with ConcurrencyMode set to "Fixed" for optimistic concurrency checking. I increment the value of this column in my application code before saving an entity of this type (so StoreGeneratedPattern is set to None). This works well when saving changes.

Now I also would like to detect a concurrency error when I have a previously loaded entity (with ROW_VERSION = x) and I create a new DbContext, attach this entity and issue a query involving this entity. The problem there is that if the ROW_VERSION was incremented by another client application (ROW_VERSION = x + 1), this isn't detected during my query, because the value of the attached entity has obviously priority (which totally makes sense for common column values).

For my concurrency checking column on the other hand it would be nice, if the EF updates the value with the current databasevalue, so I can compare it with the expected value. Alternatively an exception thrown from the query execution would be acceptable.

I'm using entity framework 4.3 with .NET 4.0.

Edit (in response to the comment from Gert Arnold):

I try to clarify my problem a little more ...

Notes of how my application works generally:

  • There is a treeview showing my available entity objects and on selecting one, the full entity is loaded from DB to be displayed in a detail view, where it can be edited

  • Modifications to an entity object are not saved immediately but are cached in memory, so modifications of different entity objects can pile up and are saved all together, when the user hits the save button.

  • DbContexts are created separately for queries and saving changes (i.e. I don't have the same DbContext all the time, but they are instantiated as needed).

  • When an entity object is loaded to be display in the detail view, all previously modified entity objects (that are cached) are attached to the DbContext that is used for the query first. Then the actual query is issued. So if i query an entity object, that was modified before I will get the modified version as result and not the version from database (which could have changed in the meantime).

So here is an example that shows my problem:

  1. Client App 1 loads an entity object with ROW_VERSION = 1, disposes the DbContext and keeps the reference to this entity object for further editing.

  2. Client App 2 loads the same entity object mentioned in step 1, changes a property and saves the changes. This causes the ROW_VERSION in the DB to be incremented (it is 2 now).

  3. The user of Client App 1 now changes some properties of entity object (which is still in memory with a ROW_VERSION of 1).

  4. Before Client App 1 saves the changes, it loads some other entity objects for display, and eventually selects the entity object in question again (e.g. to review the changes made). This causes a query where the result will contain the already changed entity object (because it is attached to the DbContext before the actual query is sent to the database).

    And here is my problem: At this point the entity framework could compare the ROW_VERSION of the attached object with that of the object in the actual query result, detect a mismatch and e.g. throw an exception.

    But instead the EF treats the ROW_VERSION property like all other properties which could just have been changed by the client.

So I wish the EF to treat the ROW_VERSION property specially and compare its values on every query to detect changes by other clients. This way I would detect concurrency situations earlier than when waiting for the SaveChanges call.

War es hilfreich?

Lösung

I think I understand now, but I don't see how Entity Framework could help you here.

  1. Optimistic concurrency per definition is a strategy to handle conflicts when committing data. Not when reading data. So it would be a departure from expected behaviour if ConcurrencyMode would be implemented this way (even when configurable).
  2. Suppose EF entities classes could be configured to behave like this on reads. It would be very hard to deal with all possible exceptions when retrieving a list of these entities or an object graph containing these entities. Should the whole read be rolled back? So it would probably only be useful when reading individual entity objects. That would be a very (read: too) fine-grained configuration specification.

As far as I can see if you want this early warning system you'll have to program it yourself. That should involve some query to read the version value specifically, because Refresh with StoreWins (ObjectContext) or Reload (DbContext) always overwrites all values.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top