More on change tracking...
Frans Bouma has an excellent post about Why change-tracking has to be part of an entity object. I like the level that he has gotten into, but I don't agree with his conclusion.
The main issue is about a disconnected scenario, where you object went somewhere, and then came back, and you don't know what hapepned to it in the middle. Frans gives an excellent description about how it works in the infrastructure level using the ASP.Net data source, which I will continue to use.
The main problem here is not change tracking per-se, it is state management. Many of the things that we do are inheritently stateless. The web is stateless, web services are stateless, etc. The entire idea of change tracking has the underlying assumption that I am tracking the state in some manner.
As Frans points out, there are few options to handle this state.
- You can put it in the view state, which is what the default GridView over DataSet does, and watch how the page sizes reaches the megabytes levels.
- You can put it in the user session object, in which case you are suffering from increased memory usage and have a lot more headache if you want to scale up.
- You can serialize the original state somewhere, to a file or to the database, and load it after ward.
At any rate, this is not a trivial manner, and there are plenty of design decisions that have wide ranging affect on your project. In Frans words:
And right now we moved from change tracking to concurrency tracking. There are solution for those, optimistic concurrency is probably the best idea here, and that requires some sort of a flag to notify us if the row has changed or not. In SQL Server, this is usually handled by TIMESTAMP column, which is guranteed to change to every time you modify the row.
The process now is to:
- Get the objects from the database
- Set the new values, including the old TIMESTAMP value
- Save to DB
- Handle the concurrency violations
This is still not trivial, but it have moved from having to handle infrastructure issues to having to handle business logic issues (what to do when there is a concurrency violation is a business decision).
Comments
Keep in mind that Sqlserver is the only db (ok sybase as well I think) which has a timestamp type which is controlled by the DB system. If that's not done, you need original values to perform any form of concurrency control. I pulled that into the discussion as it belongs to the complete picture, which is what the framework user is faced with anyway.
You can get the same functionality by using a trigger, or a simple version column with numeric value, that is incremented from the previous value on save.
Having it in the DB is nice, but is not a requirement.
Oh that's right! :X Didn't think of that... crawls back into corner :)
Timestamp is a nice thing if you've got it. But lets face it most tables don't have a timestamp or equivalent column. So the only option you have doing updates restricted to rows with ALL of the old values (including the key of course).
This BTW is how you can do transaction management at the DB level without using locks. Using snapshoting techniques. When the transaction commits it check all previous page data against the live database page and if the same the process the update can continue.
My personal opinion is that entities should have a sort of data dependence injection going on. They should bind to a sort of uplevel datarow... that tracks current and previous values etc. In this way the entities can remain relatively simple but the updates can be restricted appropriately etc.
Comment preview