Telerik OpenAccess ORM Mapper : Lessons Learnt
When looking at developing new applications I always end up developing my own data layer. Largely because I do not like the dictatorial design principles spouted by the likes of ActiveRecord, nHibernate, et al. I write them according to real life situations where database design isn't as clean as it perhaps should be and there is no opportunity to make key changes, etc. And you know what, rolling your own is so much easier and much less hassle.
For my current project, though, I thought I'd try something "new" ...
I have been looking at Telerik's new OpenAccess ORM application recently. Telerik acquired the software a while back and have introduced it into their excellent value Premium RadControls product suite. The Express version is a good way to investigate if it is for you, so long as you are using it on a "free" database server such as SQLExpress, SQLLite, etc.
I thought I'd jot down some quick lessons I have learnt along the way.
Templates
My coding style does not match Telerik's code style as generated from the OpenAccess Reverse Engineering option. Whereas Telerik's generated form of a private member is in the format:
private string siteName;
My preferred style is:
private string _siteName;
There are few things more frustrating than adopting someone elses coding style, so I set about investigating how to get around this.
There are a number of templates that define how the classes are built when you Reverse Engineer, which are stored in the C:\Program Files\Telerik\OpenAccess ORM\sdk\IDEIntegrations\templates\PCClassGeneration folder (or your equivalent).
To change the private member format, you need to open all the files and look for a reference to the "$fieldName" variable. I changed this to "_$fieldName" and it generated the correct code.
It did not, however, generate the correct mappings, which are stored in the reversemapping.config and App.config files, which I had to tweak manually. I still have a forum post outstanding on this one.
Deferred Execution
If you get an "IObjectScope is closed" exception, you'll probably be doing something intelligent like creating a nice Factory Design Pattern, whereby you get your object within the IObjectScope and return it out for use by your BIZ objects. OpenAccess execution is deferred, however, which means if you access any of the properties outside of the IObjectScope context, you get the exception. So, for my factory method that Gets a Site object:
public object Get(Guid id)
{
Site site = null;
using (IObjectScope scope = Database.Get(_session.ConnectionId).GetObjectScope())
{
scope.Transaction.Begin();
using (IQueryResult result = scope.GetOqlQuery("SELECT * FROM SiteExtent").Execute())
{
if (result.Count > 0) site = (Site) result[0];
string s=site.SiteName;
}
scope.Transaction.Commit();
}
return site;
}
Note that I access the site.SiteName property and discard it. This just forces OpenAccess to perform the Get and put the Site object into memory so when I drop out of the method, I don't lose the object.
Using LINQ
Telerik say their Open Access solution is a mid point between LINQ to SQL and Entity Framework. Seems good to me, but there are a few gotchas you need to know about.
As with anything in the OpenAccess ORM (unless you are working with SQL directly), you don't work with tables, you work with Extents. The non-LINQ way of doing things int he code sample above shows the OQL query "SELECT * FROM SectionExtent". The table name is Section, but OpenAccess maps it into an Extent. The same model works when using LINQ. Before you can start using Extents in LINQ, you need to add the Telerik.OpenAccess.Query namespace.
If you're using of the Telerik products, you might want to follow @telerikbuzz on Twitter for useful information and updates.