Concurrency is a tough subject and is solved by a lot of different methods during the years. Because supporting simple systems like optimistic or pessimistic control would limit your options how exactly the concurrency control would be implemented, we've added facilities to let you extend the save and delete methods with functionality to implement your own concurrency support the way it fits your needs. For example you can specify a predicate expression with the save or delete methods to make the save or delete method test for the predicate to be true to proceed, otherwise to fail. This way you can create concurrency control based on a timestamp column, but also on a range of columns. Furthermore you can extend the actual save / delete methods so you can stop the save or delete process if your added logic finds proceeding would violate a concurrency rule.
LLBLGen Pro supports another form of supplying predicates for filters during Save or Delete actions: implementing an interface: IConcurrencyPredicateFactory. You can implement this interface to produce, based on the type of action (save or delete) and the entity the predicate is for, an IPredicateExpression object which is then used as the filter for the action (Save or Delete). Each entity object has a property, ConcurrencyPredicateFactoryToUse, which can be set to an instance of IConcurrencyPredicateFactory. If specified, each Save() and Delete() call on the entity will consult this object for a filter object. This is also the case for recursive saves. If you want concurrency control deep down a recursive save, it's key that you set those object's ConcurrencyPredicateFactoryToUse property to an instance of IConcurrencyPredicateFactory. IConcurrencyPredicateFactory instances can't be shared between Adapter and SelfServicing code. The documentation contains an example implementation of IConcurrencyPredicateFactory, which returns predicates which test for equality on EmployeeID for the particular order. This will make sure the Save or Delete action will only succeed if the entity in the database has the same value for EmployeeID as the in-memory entity.