1
votes

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
POCO and STE ( self tracking entities ) are two different t4 generation strategies that can't be used together. Can you clarify what you mean? - John Farrell
They are no longer two different strategies. You can have both. See blogs.msdn.com/adonet or more specifically you can get the templates here visualstudiogallery.msdn.microsoft.com/en-us/… - Mark Lindell
"Self Tracking Entities" is a totally different T4 template, see more information on the ado.net blog. POCO != Self Tracking Entities. - John Farrell
I understand they are two differt templates but the ste templates seem to just add tracking support to the entities without any dependency on the EF. So why wouldn't the generated class files be considered POCO? - Mark Lindell

2 Answers

2
votes

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.

0
votes

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.