Assume I have User entities, Role entities, and a n:m relationship between User and Role, supported by the UserRole entity. Assume User entities have a .Roles collection holding the user's roles.
Assume the business layer gives me a User entity, wich I must save. Following several posts in the forums, here is how we do it, wrapped in a transaction:
adapter.SaveEntity(user)
adapter.DeleteEntitiesDirectly("UserRole",
new RelationPredicateBucket(UserRoleFields.UserId == user.Id));
foreach (Role r in user.Roles)
{
UserRole ur = new UserRole();
ur.UserId = user.Id;
ur.RoleId = r.Id;
adapter.SaveEntity(ur);
}
However, since SaveEntity(user) may not actually trigger an UPDATE in the database (if no fields have changed), the following scenario is possible:
Thread #1 updates the user, actually trigger an UPDATE
Thread #2 updates the user, does not trigger an UPDATE
Thread #2 deletes roles
Thread #2 inserts new roles (wait...)
Thread #1 deletes roles (deadlock)
There is a way to prevent this, by adding a timestamp field to User and implementing an optimistic concurrency check. This would ensure that an UPDATE is always triggered, thus causing Thread #2 to wait when trying to update the user.
Any way to achieve the same result without adding a timestamp (bearing in mind that we can not select "for update" with LLBL)?