I blatantly stole all of this off the internet, with minor changes from From example:[http://adriandev.blogspot.com/2007/12/optmistic-concurrency-withtimestamps.html](http://adriandev.blogspot.com/2007/12/optmistic-concurrency-withtimestamps.html)
- Concurrency Classes - A file to be placed in your LLBL project. EntityClass section worked for me. This factory will auto add in to all your entities. So they all need to have the same field ModifiedDate. If you have cases where you need a different Concurrency mechanism you can override it on the save.
- Trigger - to ensure Modified Date is updated.
- Example on how I used it.
1. Example Concurrency Class
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Text.RegularExpressions;
using SD.LLBLGen.Pro.ORMSupportClasses;
using glossaryDB;
using glossaryDB.FactoryClasses;
using glossaryDB.DaoClasses;
using glossaryDB.RelationClasses;
using glossaryDB.CollectionClasses;
using glossaryDB.HelperClasses;
using glossaryDB.EntityClasses;
namespace glossaryDB.EntityClasses
{
/// <summary>
///
/// </summary>
public partial class CommonEntityBase
{
protected override SD.LLBLGen.Pro.ORMSupportClasses.IConcurrencyPredicateFactory CreateConcurrencyPredicateFactory()
{
return new OptimisticConcurrencyFactory_ViaTimestampCheck();
}
public string ConcurrencyCheckFieldName
{
get { return _concurrencyCheckFieldName; }
set { _concurrencyCheckFieldName = value; }
}
private string _concurrencyCheckFieldName = "ModifiedDate";
}
/// <summary>
///
/// </summary>
public class OptimisticConcurrencyFactory_ViaTimestampCheck : IConcurrencyPredicateFactory
{
public IPredicateExpression CreatePredicate(ConcurrencyPredicateType predicateTypeToCreate, object containingEntity)
{
IPredicateExpression toReturn = null;
CommonEntityBase entity = (CommonEntityBase)containingEntity;
//EntityBase entity1 = (EntityBase)containingEntity;
if (!string.IsNullOrEmpty(entity.ConcurrencyCheckFieldName))
{
toReturn = new PredicateExpression();
IEntityField lastModifiedDateField = entity.Fields[entity.ConcurrencyCheckFieldName];
switch (predicateTypeToCreate)
{
case ConcurrencyPredicateType.Delete:
case ConcurrencyPredicateType.Save:
toReturn.Add(new FieldCompareValuePredicate(lastModifiedDateField, ComparisonOperator.Equal, lastModifiedDateField.CurrentValue));
// Don't use DbValue -> this seems to repull this value immediately here which is different then what we need.
break;
}
}
return toReturn;
}
}
}
2. Trigger
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO
ALTER TRIGGER [dbo].[tr_UserAccount_Concurrency] ON [dbo].[UserAccount] FOR INSERT, UPDATE
AS
BEGIN
UPDATE UserAccount SET ModifiedDate = getdate()
FROM UserAccount INNER JOIN inserted ON UserAccount.UserAccount_ID = inserted.UserAccount_ID
END
3. Example Use- from my MVC app
UserAccountEntity e_UserAccount = new UserAccountEntity();
try
{
//UpdateModel(e_UserAccount);
e_UserAccount.UpdateFrom(Request.Form);
e_UserAccount.Save();
}
catch (ORMConcurrencyException ex)
{
this.ModelState.AddModelError("Exception", "Sorry, another user has already updated this User Account record");
return this.View("edit", e_UserAccount);
}
return RedirectToAction("Index");
I removed all the validation wrappers etc from this to keep it clean.