Hi all
It has been a good time once again to share with you what i am trying to do. Apart from sharing also i want to get other insight form others . As what my collegue out there are thinking in regard to the issue of caching.
For a long time i have trying to have a generic cache which is a first class citizen in the csla.net framework .
To have a first class cache for csla.net is no an easy task due to many reason but the most intuitive once are:
1) CSLA.NET is not tied to any data access technology. So the idea of intercepting queries and targeting to the cache is very ideal for you have to define the query interceptors for all data access technoligies.
2) CSLA.NET objects are mobile so its data access can run locally or at the server . IF the cache is locally located fine but when you change form 2 tire to 3 -tire the cache will be have to be tuned accordingly of course a lot of work.
3) CSLA.NEt objects are designed to work even in the silverlight runtime. so any cache to support the objects are also need to accomodate the behaviour of silverlight if at all we want to honour the easy of switching the objects working in windows environment to silverlight runtime
Due to all that reason i have come up with the attached code which follows these design decisions.
- I dropped the idea of incorparating the cache into fething XYZ-dataportal methods as their execution location is not known( locally or at the server ?).
Also putting the cache is the fetching XYZ methods does not bring sense as XYX methods are to be intercepted ( the should be called only if there is not data at the client)
Lasty the cache should be working also in the silverlight runtime where there is not xyz methods (if not local proxy)
- I dropped the idea of query interceptors due to absence of supported in csla.net data access technology( which is good)
Also query interceptors are not feasible if the cache is to work in the silverlight environment for the query structure has some dependency on the structure dataaccess technology. Escpeciaaly of ADO.NET EF , LINQ to SQL which their definitions i dont know if they can deployed in the silverlight runtime.
The options lead me to:
1)Intercept execution of dataportal xyz fetch methods and not query result.
So the developer ends up doing whatever in the xyz and the cache is totally ignorant to the logic i n the xyz
How it does.
First we cache csla.net Objects and not raw data.
So if you have two different objects(classes) with the same data( Database table as well columns) they will all be cached as two different cacheitem
The only thing i could use to intercept execution of dataportalXYZ fetch method is by using the criteria objects.
IF ANY FETCH METHOD IN AN OBJECT EXECUTES ONLY ONE SQL COMMAND
IT CAN BE SAID THAT CRITERIA OBJECT IS REPRESENTS THE QUERY
Before any execution the cache constructs the key from criteria object .
Private Function CreateKeyString(Of T As csla.Core.MobileObject)(ByVal key As Object) As String
Dim _key As String = GetType(T).FullName + key.GetType.FullName
For Each df In key.GetType.GetProperties
_key = _key + df.GetValue(key, Nothing).ToString()
Next
Return _key
End Function
The function has a generic type T which passes the type which a criteria is for. This is so since there a re some citeria which will be used by more than one type. There are other possibilites here is see especially if the criteria is of type criteria base. But the function is private no worry much.
The method constructs the key by getting the values of the criteria objects and the name of the object .The result is that the key will be unique for any call.
Another thing is that i have written a cachefactory, to be renamed to cachedataportal or ....? i dont know.
Its main entry point is
Public Function GetCache(ByVal name As String) As Cache '(Of csla.Core.MobileObject)
Return GetCache(name, 10, True)
End Function
Public Function GetCache(ByVal name As String, ByVal expiryTime As Integer, ByVal allowOffLine As Boolean) As Cache '(Of csla.Core.MobileObject)
If Not caches.ContainsKey(name) Then
CreateCache(name, expiryTime, allowOffLine)
End If
Return caches(name)
End Function
Private Sub CreateCache(ByVal name As String, ByVal validDuration As Integer, ByVal AllowOfLine As Boolean)
caches.Add(name, New Cache(name, validDuration, AllowOfLine))
End Sub
Private Function GetCache() As Cache
Return GetCache("default")
End Function
I have the idea of the concept of named cache. You can have different a policies on different type of objects. rather than defining on each obects you can define a cache with name, ExpiryTime as well as it can be offline or not and other(to be done).
Then objects will be cached in their allocated cache.
Default cache is named "default", with 10 minuted validDuration and AllowOFLine of false.
If the cache is not there it will be created
Private _caches As Dictionary(Of String, Cache)
Private Sub CreateCache(ByVal name As String, ByVal validDuration As Integer, ByVal AllowOfLine As Boolean)
caches.Add(name, New Cache(name, validDuration, AllowOfLine))
End Sub
//FOR WINDOWS
Public Function Fetch(Of T As csla.Core.MobileObject)(ByVal criteria As Object) As T
Dim _cache As Cache = Nothing
If TypeOf criteria Is CachableCriteria Then
_cache = GetCache(CType(criteria, CachableCriteria).CacheName)
Else
_cache = GetCache()
End If
Return _cache.Get(Of T)(criteria)
End Function
// FOR SILVERLIGHT
//INCOMPLETE but latery before current refactoring it worked
//Italiced words needs to be removed . I am sory
Public Function BeginFetch(Of T As csla.Core.MobileObject)(ByVal criteria As Object) as T
Dim _cache As Cache = Nothing
If TypeOf criteria Is CachableCriteria Then
_cache = GetCache(CType(criteria, CachableCriteria).CacheName)
Else
_cache = GetCache()
End If
' Return _cache.
End Function
I have also defined the CachableCriteria inherits from Criteria base
<Serializable()> _
Public MustInherit Class CachableCriteria
Inherits csla.CriteriaBase
Public Overridable ReadOnly Property CacheName() As String
Get
Return "default"
End Get
End Property
End Class
This is designed so that you can define in which cache the criteria result should be cached. And all the policies defined on the cache will be applied to the result.
If you just want to use the default cache just inherit the criteria from criterabase or do as you like.
To save in the other cache inherite the criteria object from the CachableCriteria class and override the cache name returning the cachename to be used otherwise it will end up using the default cache.
For modification: I plan to have another cache class property IsEnabled with default true. In case one anticipate to use the cache but not for now.
How to use.
Look in the class2
In the factory
Public Shared Sub GetClass(ByVal age As Integer)
CacheFactory.Fetch(Of Class2)(New NGH(age))
End Sub
The cach will call dataportal fetch in case the object is not cached or is invalidated.
The cachefactory/cache can be also the dataportal by itself not decided.
Note i just made this codes yesterday. so they are mainly proof of concept and not tested vigourously apart from the example
Of line /Online capability will be added. By having the classes inherit from CachableBusinessBase (to be writtern) which will override Save and BeginSave and just check the factory if online proceed otherwise check validation rules if valid serielize and/or encrypt to disk.
We shall add the fonfiguration capabity so that the names and policies of caches can be defined in the configuration file.
Should the configuration file( or just a file) be placed in the application server so that the changes are automatically rolled to all client ??
There is a work to hook the objects saved event in the cache.
The cache caches only the parent objects but it has not tested against other objects stereotypes such as lists and readonly. Obvious it will not cache command objects(at least for now)
There are many design issues and actual work to be done.
The project for silverlight and Windows share the same files , assembly name though i dont think the cache itself will move between the two runtime, but think it will enable the same csla.net obects two function between the environments with easy while maintaining/using the cache.
The root namespace is csla for easy usage.
Note still under development so very flagile codes
The thanx for your hand
Ayubu
Copyright (c) Marimer LLC