Showing posts with label Web Service. Show all posts
Showing posts with label Web Service. Show all posts

Thursday, December 27, 2007

Optmistic Concurrency withTimestamps, LLBLGen and Web Services

Found a great article on how to implement optimistic concurrency with LLBLGEN and SQL Server:

Optmistic Concurrency and Timestamps in SQL Server Using LLBLGen Pro O/R Mapper by David Hayden.

Now, I am using XML Web Services and passing entities back and forth, and what I have found is that the DBValue property on each field is NOT serialized! I have not found a better solution as yet, but I am currently just using the field's CurrentValue. So, assuming the timestamp properties used do not get changed on the client, it will work, but this is a problem that will need to be fixed.

Update: Looks like there was an issue with the deserialization in version 2.5 (October 25 2007 release). The December release has apparently fixed this issue:

http://www.llblgen.com/TinyForum/Messages.aspx?...

Modifications with LLBLGEN 2.5

I am inherently lazy, which is a bad thing when it comes to coding, but the solution described by LLBLGEN's help and David Hayden relies on a factory class for each entity. Sure, we should probably modify the templates and create a new factory class for each of our entities, but for what I wanted, that sounded like too much work.

Now, in LLBLGEN 2.5, all entities are now derived from another generated partial class called CommonEntityBase. And, lets face it, we are probably going to create our timestamp field on every entity and call it the same name (in this case, every entity has a timetamp field called LastModified). So, I created a new partial class definition for CommonEntityBase that allows me to get access to the timestamp field I will use for all entities' concurrency control.

public partial class CommonEntityBase
{
private const string LAST_MODIFIED_FIELD_NAME = "LastModified";

public IEntityField2 LastModifiedField
{
get { return this.Fields[LAST_MODIFIED_FIELD_NAME]; }
}
}

This then allows me to create a single factory for concurrency predicate expressions:
public class EntityConcurrencyFactory : IConcurrencyPredicateFactory
{
public IPredicateExpression CreatePredicate(ConcurrencyPredicateType predicateTypeToCreate,
object containingEntity)
{
IPredicateExpression toReturn = new PredicateExpression();
CommonEntityBase entity = (CommonEntityBase)containingEntity;

switch (predicateTypeToCreate)
{
case ConcurrencyPredicateType.Delete:
case ConcurrencyPredicateType.Save:
// only for updates
toReturn.Add(new FieldCompareValuePredicate(entity.LastModifiedField,
null, ComparisonOperator.Equal, entity.LastModifiedField.CurrentValue));
break;
}
return toReturn;
}
}

Two classes for all entities - sounds good to me. Now, using David's example, there isn't any difference in the code (just every entity uses the same factory):
DataAccessAdapter adapter = new DataAccessAdapter(...);

BlogEntity blog = new BlogEntity();
blog.BlogId = 1;

adapter.FetchEntity(blog);

blog.Name = "New Name";

IPredicateExpression expression = new EntityConcurrencyFactory()
.CreatePredicate(ConcurrencyPredicateType.Save, blog);

adapter.SaveEntity(blog, true, expression);

You can still change optimistic concurrency strategies easily, but it is easier to apply to all of your entities at once.

Tuesday, November 27, 2007

Using LLBLGEN Generated Classes with Web Services

UPDATE: This only applies to version 2.0.

If you are using LLBLGEN with Web Services and you want to return entities and views to the client, you should have configured your machine to work according to the LLGBLGEN article titled Generated code - XML Webservices support.

This works nicely with Entity Classess, and probably Typed Lists (which I haven't used/tested yet), but there is a problem with Typed Views. If you have a Web Method that returns one of your Typed Views, you are probably getting errors generating the proxy classes, or the type specified in the proxy class that is generated does not match the Typed View in your Web Method!

There appears to be a bug in the webServiceHelper.template file that is used by the LLBLGEN generator. You can find this file in the following directory:

C:\Program Files\Solutions Design\LLBLGen Pro v2.0\Templates\SharedTemplates\Net2.x\C#

Open the file in a text editor and look for the following line in the "TypedView Classes" region:

return new XmlQualifiedName("<[CurrentTypedListName]>TypedList", namespaceToUse);

Change the above line to:

return new XmlQualifiedName("<[CurrentTypedViewName]>TypedView", namespaceToUse);

Now instead of having every one of your typed views with an XmlQualifiedName of TypedList, it is actually to the name of the class. Look in WebServiceHelper.cs (or WebServiceHelper.vb) to confirm this change is working.

I generally find that these changes only affect the proxy generation when the service reference is recreated; updating the reference doesn't always work.

Powered By Blogger