How to leverage concurrency checking with EF 4.0 POCO Self Tracking Entities in a N-Tier scenario?
I'm using VS1010RC with the POCO self tracking T4 templates.
In my WCF update service method I am using something similar to the following:
using (var context = new MyContext())
{
context.MyObjects.ApplyChanges(myObject);
context.SaveChanges();
}
This works fine until I set ConcurrencyMode=Fixed on the entity and then I get an exc开发者_如何学JAVAeption. It appears as if the context does not know about the previous values as the SQL statement is using the changed entities value in the WHERE clause.
What is the correct approach when using ConcurrencyMode=Fixed?
The previous values need to be in your object.
Let's say you have a property ConcurrencyToken
:
public class MyObject
{
public Guid Id { get; set; }
// stuff
public byte[] ConcurrencyToken { get; set; }
}
Now you can set ConcurrencyMode.Fixed
on that property. You also need to configure your DB to automatically update it.
When you query the DB, it will have some value:
var mo = Context.MyObjects.First();
Assert.IsNotNull(mo.ConcurrencyToken);
Now you can detach or serialize the object, but you need to include ConcurrencyToken
. So if you're putting the object data on a web form, you'll need to serialize ConcurrencyToken
to a string and put it in a hidden input.
When you ApplyChanges
, you need to include the ConcurrencyToken
:
Assert.IsNotNull(myObject.ConcurrencyToken);
using (var context = new MyContext())
{
context.MyObjects.ApplyChanges(myObject);
context.SaveChanges();
}
Having ConcurrencyMode.Fixed
changes the UPDATE
SQL. Normally it looks like:
UPDATE [dbo].[MyObject]
SET --stuff
WHERE [Id] = @0
With ConcurrencyMode.Fixed
it looks like:
UPDATE [dbo].[MyObject]
SET --stuff
WHERE [Id] = @0 AND [ConcurrencyToken] = @1
...so if someone has updated the row between the time you read the original concurrency token and the time you saved, the UPDATE
will affect 0 rows instead of 1. The EF throws a concurrency error in this case.
Therefore, if any of this isn't working for you, the first step is to use SQL Profiler to look at the generated UPDATE
.
Mark,
The objects created as "Self-tracking entities" cannot be considered pure POCOs;
Here's the reason: The STEs only work well if your client uses the generated proxies from the STE T4 template. Change-tracking, and thus your service, will only work with these generated proxies.
In a pure POCO world (interoperatibility, Not all .Net 4.0 clients, .. ), you cannot put constraints on you client. For instance, facebook will not be writing a service that can only handle .Net 4.0 clients.
STEs may be a good choice in some environments, it all depends on your requirements.
精彩评论