I’m glad to announce that the new version of Magiq is available.
Magiq now support:
- Plugin model
- BulkCopy as a Plugin for using SqlBulkCopy when inserting into sql server from any source.
And also there was a huge refactoring in order to have simplicity when implementing new providers.
You can download this version from here.
I’m glad to annunce that the first version of Magiq is finished. It fully supports Magiq-to-objects and Magiq-to-sql.
The future plan includes Magiq-to-NHibernate and Magiq-to-Entities.
You can download it here. Also, you can read the brief documentation.
I will continue with the Magiq saga. You can read the previous posts:
- It’s a kind of Magiq
- Magiq: The story of the API that wasn’t
- Magiq: Playing with linq-to-sql internals
- Magiq: Mass inserts and deletes with linq-to-sql
Today is the turn of Magiq-to-objects. Having the basic interface needed for the most simple linq-to-sql mass operations, I tried to make it work with objects (ie. using a List as a repository).
I thought it would be easy, because all is lamba expression-based. The problem is that I forgot we changed the api, so we don’t have an actual update expression. Instead, we have a lot of property sets:
products.Where( x=> x.ExpirationDate <= DateTime.Now ) .Set( x=> x.State, ProductState.Expired ) .Update();
The only way we could actually update a property from a lamda expression representing the getter of the property is using reflection, so we do it that way. Basically, you could inspect the lambda expression until you get to the PropertyInfo object. Having the PropertyInfo, it’s just reflection.
Since we had the where clause, it was easy to compile it and using to filter the enumerable. The problem was I need to remove the items from the original list! QuickWatch helped me again. Basically you have two kind of queries that would be handled by this: EnumerableQuery and WhereEnumerator (or something like that). The first one is what you get when you call the AsQueryable() extension method in a enumerable. The second one is the result of calling the Where extension method.
For WhereEnumerator, there is a private Field called source. You could recursive search it until you get to the main list. For EnumerableQuery, the list itself is like a constant expression inside a big lamda expression. It turned a little messy, but finally we could found the list.
This was the most easy of the implementations. Since the API give us the “new” expression and for the delete we already got the original list, it didn’t give us any trouble.
Bonus track: Dynamic Reflection
We needed a lot of reflection in order to have things working. But we hate reflection. Mostly, because it’s performance. But more because the lack of a good API in linq-to-sql. Ugly or not, we have to use reflection in order to have Magiq working. I googled for something like NHibernate’s reflection optimizer, but what I found wasn’t exactly what I wanted. So we implement some DynamicMethods directly in IL in order to get a respectable performance. This week I will be removing the code from Magiq and I’ll create a new project in codeplex for this. The main idea is to be able to do the same as with reflection, but dynamically.
And this is the story about how we implemented Magiq-to-objects.