Injecting into the ECO cache
In my previous post I showed an interface ILockable. The actual interface is
Any lockable resource implements this interface. In its constructor it creates an instance of a class which descends from LockObject, a Document class for example would create an instance of DocumentLockObject which descends from LockObject. The "Document" class would store away the ID of the DocumentLockObject in a private attribute. Now when my LockingService is asked to lock multiple (un-related) instances which implement ILockable I want to do this
1: Create a new EcoSpace
2: Load objects efficiently
3: Get locks
4: Update the DB
5: Dispose of the EcoSpace
If I experience an OptimisticLockingException then loop and try again. The item I would like to discuss is #2, "Load objects efficiently". In my model a LockObject has a *--1 association to Session identifying which session has locked it, I want to ensure that the LockObject + LockObject.ExclusiveLockedSession instances are loaded as quickly as possible. If I have a collection of LockObject I can easily use the following code to efficiently load all relevant sessions
This extension method assumes that the association name is the same as the class’s property name and is implemented like so:
This is possible because I have a list of ECO class instances as my basis and can therefore rely on the ExclusiveLockedSession association to get ECO to quickly load the related objects. The problem I need to solve is this: given an interface (ILockable) how do I get all LockObjects? Remember that these lockable objects (Document, Image, Video, etc) have no common superclass and therefore have no common association to their LockObject, and this is exactly why I wanted to know the LockObject’s primary key in my last post.
Given a collection of ILockable I am able to determine 2 things.
1: The primary key of its LockObject
2: The exact type of the LockObject it refers to (DocumentLockObject, VideoLockObject, etc).
In my new EcoSpace instance I can now inject locators for these objects directly into the cache.
public interface ILockable
{
Guid GetLockID();
Type GetLockObjectType();
}
Any lockable resource implements this interface. In its constructor it creates an instance of a class which descends from LockObject, a Document class for example would create an instance of DocumentLockObject which descends from LockObject. The "Document" class would store away the ID of the DocumentLockObject in a private attribute. Now when my LockingService is asked to lock multiple (un-related) instances which implement ILockable I want to do this
1: Create a new EcoSpace
2: Load objects efficiently
3: Get locks
4: Update the DB
5: Dispose of the EcoSpace
If I experience an OptimisticLockingException then loop and try again. The item I would like to discuss is #2, "Load objects efficiently". In my model a LockObject has a *--1 association to Session identifying which session has locked it, I want to ensure that the LockObject + LockObject.ExclusiveLockedSession instances are loaded as quickly as possible. If I have a collection of LockObject I can easily use the following code to efficiently load all relevant sessions
objectSpace.EnsureRelatedObjects(result, x => x.ExclusiveLockedSession);
This extension method assumes that the association name is the same as the class’s property name and is implemented like so:
public static class PersistenceServiceExtender
{
public static void EnsureRelatedObjects<T>(
this IEcoServiceProvider instance,
IEnumerable<T> objects,
Expression<Func<T, object>> member
) where T : IEcoObject
{
MemberExpression memberExpression = (MemberExpression)member.Body;
var ps = instance.GetEcoService<IPersistenceService>();
ps.EnsureRelatedObjects(objects, memberExpression.Member.Name);
}
}
This is possible because I have a list of ECO class instances as my basis and can therefore rely on the ExclusiveLockedSession association to get ECO to quickly load the related objects. The problem I need to solve is this: given an interface (ILockable) how do I get all LockObjects? Remember that these lockable objects (Document, Image, Video, etc) have no common superclass and therefore have no common association to their LockObject, and this is exactly why I wanted to know the LockObject’s primary key in my last post.
Given a collection of ILockable I am able to determine 2 things.
1: The primary key of its LockObject
2: The exact type of the LockObject it refers to (DocumentLockObject, VideoLockObject, etc).
In my new EcoSpace instance I can now inject locators for these objects directly into the cache.
private IEnumerable<LockObject> GetLockObjects(IEcoServiceProvider objectSpace, IEnumerable<ILockable> subjects)
{
//Get a reference to the cache content service so that we can inject
var cache = objectSpace.GetEcoService<ICacheContentService>();
//Create an IObjectList, a list of object locators of type LockObjecct
var variableFactoryService = objectSpace.GetEcoService<IVariableFactoryService>();
IObjectList locators = variableFactoryService.CreateTypedObjectList(typeof(LockObject), false);
//Inject each locator directly into the cache, avoiding the DB completely
foreach (var subject in subjects)
{
Guid lockObjectID = subject.GetLockObjectID();
Type lockObjectType = subject.GetLockObjectType();
IObject lockObjectLocator = cache.GetObject(lockObjectID, lockObjectType);
locators.Add(lockObjectLocator);
}
//Now I have a list of locators I can fetch the instances from
//the DB in an efficient way by converting them to IList<LockObject>
var result = locators.GetAsIList<LockObject>();
//And finally I ensure related objects
objectSpace.EnsureRelatedObjects(result, x => x.ExclusiveLockedSession);
return result;
}
Comments