views:

534

answers:

2

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 exception. 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?

+2  A: 

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.

Craig Stuntz
A: 

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.

KoenJ
It sounds to me like the definition of POCO is weak. Plain Old CLR Object does not imply any specific version of the framework. I realize the T4 template targets features of .NET 4.0. I thought it spoke more to ORM framework dependencies. Self tracking may or may not be a requirement of individual domain object that may have custom implementations of tracking.
Mark Lindell