Archive

Archive for the ‘Magiq’ Category

Magiq to Entities – An update

May 7, 2011 2 comments

The past days I’ve been working on making Magiq work with Entity Framework.

First I tried to work with the MetadataWorkspace and I gave up, ’cause its really impossible to get the mapping information. Luckily, I found Linq to Edmx project who does exactly what I needed.

Then I had some troubles working with the Queryables generated by the ObjectSets. Basically, the expression generated calls methods that doesn’t work and are there only to give information in the expression. So the expression is not something you can compile and execute. As big part of Magiq is to manipulate expression trees, that was a really big problem. I needed to figure out how to change the source queryable (I mean, the queryable where all the methods are applied to) to a simple ObjectSet. Besides it works now, I’m still working to get to a nicer way (you don’t want to know what I have done to make it work…).

Since I changed the insert API from having the new item expression (the new{…}) outside to have it as a select, I had to break the query in two, the select and the “rest”. Ok, that gave me more headaches :).

But the biggest problem was when Entity Framework started to change the order of the columns in the select (and add new columns). Let me explain how Linq to Sql works:

If you do this:

items.Where( ... ).Select( x => new { A = x.Prop1, B = x.Prop2, C = x.Prop2 /*again*/ });

Linq to sql transate it to:

SELECT prop1, prop2, prop2 FROM items WHERE ...

But Entity Framework removes the repeated columns and maybe reorders them, giving you something like:

SELECT prop2, prop1 FROM items WHERE ...

You don’t have any idea of the reflection tricks I had to make to get those property-select columns mapping.

But well, those are not bad news at all. I mean I could work around them and I can say Magiq now supports Entity Framework (with a few restrictions). Those are:

  • Only Table per class hierarchy inheritance is supported. I’m currently working on the Table per concrete class and Table per type strategies
  • Only mapped associations are supported. This means associations based on foreign keys are not (yet).
  • Only mapped POCOs are supported. This means Self Tracking entities and Code First are not (yet).

Keep in touch for the updates 🙂

Advertisements

Magiq: New release and API Changes

April 28, 2011 Leave a comment

New release of Magiq, supporting Linq-to-sql. This should be the last one for Linq-to-sql, the next one I hope will have the minimal support for Entity Framework. You can download it from here.

For those reading this for the first time (?), Magiq is a framework that let you do mass operation in a Linq fashion.

So… as Magiq will be supporting Entity Framework soon, it made sense to change the API to make it support Entity Framework limitations. Also, I found a better Insert API (the one that always made me doubt!). The changes are:

Query extension method changes
The new method looks like this:

country.Query(x => x.Cities); 

It will return an IQueryable that will let you do all the Magiq stuff.

No more IEnumerable support
This is a hard one. You can only do Magiq stuff between IQueryables. If you have an IEnumerable collection, use the Query extension method of it parent entity.

New Insert API

destination.Insert( source.Where( condition ).Select( new Item{ ... } ));

Cool, isn’t it? 🙂

Entities extension methods
Because we no longer support extension methods over collections but over the entity, there are some extension methods for improving the code readavility.

Delete

entity.Delete(x => x.Collection.Where( condition ));
//Instead of 
entity.Query(x => x.Collection).Where( condition ).Delete();

Update

entity.Update(x => x.Collection.Where( condition ).Set(x => x.Prop, value));
//Instead of 
entity.Query(x => x.Collection).Where( condition ).Set(x => x.Prop, value).Update();

Query

entity.Query(x => x.Collection.Where( condition ));
//Instead of 
entity.Query(x => x.Collection).Where( condition );

Insert

entity.InsertInto( x => x.Collection, source.Where( condition ).Select( new Item{ ... } ));
//Instead of
entity.Query(x => x.Collection)
      .Insert( source.Where( condition ).Select( new Item{ ... } ));

Magiq: Next steps – different approach

April 25, 2011 Leave a comment

Back to the Magiq game!

I started to play with Entity Framework 4 and realized some stuff is not possible the way it was designed. It has to do with the way EF4 manages Lazy collections.
In Linq-to-sql and NHibernate, the collection itself has the property of being lazy, materializing all the objects when you iterate it. For example, in Linq-to-sql collections are EntitySets. Because of this, you can do this:

parent.Children.Delete(x => x.SomeCondition);

This is because the Children collection contains all the information needed:

  • The parent object instance, for getting the Id
  • The collection name

Sadly, EntityFramework handles this feature in a different way: Is the parent object the lazy one and the collection is populated when you access the collection propery and not when you iterate it. Because of that, in the moment you do parent.Children you have executed the query in the database.
This lead us to have a different API, that avoid accessing the collection property. What I thought is:

parent.Delete(p => p.Children.Where(x => x.SomeCondition));

It’s not so bad, I must Say, and it also let us do things like

parent.Delete(p => p.SomeObjectInTheMiddle.Children.Where(x => x.SomeCondition));

without executing the query for getting the SomeObjectInTheMiddle instance.

Also, I give up with Magiq-to-NHibernate, at least for a while. NHibernate has huge features, it let you map your classes in thousand of different ways, and that is awesome. But also it makes it really complicated to work with. And since NHibernate already has mass operation support, it makes sense to stop worring. At least, as I said before, for a while.

So, I will be working on changing the Query API and only for Linq-to-Sql and Entity Framework. Everyone is welcome to contribute implementations for other ORMs.

Next step: Changing the API

Magiq-to-Sql: Compiled queries support

November 25, 2010 Leave a comment

Back on the road with Magiq, at least for a while. I’m working on the development of a framework that could make full use of the Named Scopes feature of Magiq. The problem is that linq-to-sql needs compiled queries in order to speed up the performance and the current API is awful. So I tried to give Magiq the ability of handling compiled queries.

Since Linq is all about expression trees, I knew it will be possible to get from

var value = 3000000;
var query = country.Cities.Query( x => x.Population > value)
                          .OrderBy( x => x.Population);

to something like

var value = 3000000;
var expresson = (dc, id, value) => dc.GetTable<City>()
                                     .Where( x=>x.Id == id )
                                     .SelectMany( x=> x.Cities)
                                     .Where( x => x.Population > 100000 )
                                     .OrderBy( x => x.Population);

var query = CompiledQuery.Compile( expression );

Well, two hours of playing with the Expressions and all worked. The only/main problem is that Expressions instances are created every time so each expression object has a different HashCode and it’s impossible to cache the compiled queries by expression. Sadly, I had to add a parameter named “key” for identifying the compiled query.

This si how the final API looks like:

var value = 3000000;
var query = country.Cities.CompiledQuery( "large-cities-by-country", 
                                          (q,p) => q.Where( x => x.Population > p)
                                                    .OrderBy( x => x.Population),
                                          value );
  • The query will be identified as “large-cities-by-country”.
  • We need to pass the expression to be applied to the collection and the parameters, because we don’t want to hardcode the values in the query.

A small benchmark I’ve done with a simple model executing 5000 queries on a new DataContext each gives, this result:

  • magiq – not compiled: 36457 millisecond
  • magiq – compiled: 22295 millisecond
  • linq2sql – compiled: 22194 millisecond

Magiq-to-NHibernate: Testing for different mapping strategies

April 24, 2010 2 comments

Magiq has a set of tests for each operation (insert, update, delete and query) that should work for any provider, besides the spescific tests that could be wrote for each provider. The problem I faced when testing nhibernate was how to test several mapping strategies with the same test cases.
The good news is it’s very easy with NUnit 🙂
NUnit fully supports parameterized tests, for test cases and fixtures. Using the Parameterized Test Fixtures feature in NUnit 2.5 I created a mapping folder for each strategy to test and added the folder name as a fest fixture parameter. That’s how the test looks likie:

[TestFixture("subclass")]
[TestFixture("joined-subclass")]
public class MagiqToNHibernateInsertsInheritanceTest {
    //..
}

I love NUnit!

Back to the road

April 20, 2010 Leave a comment

Today I opened Magiq solution for the very first time in weeks. I was actually busy in the past days doing a lot of work but now I’m ready to continue the project and posting.
My next moves with Magiq is:

  • Create the unit tests for <subclass>, <join-subclass>, <union-subclass> and <any> relationships.
  • Resolve the multitable update issue.
  • Fix the unit tests, one by one.

Now I’m working on the refactor of the unit tests for supporting different mappings. I hope this will be finished by the end of the day!

In the days coming I will be working on the multitable update issue, I expect some posting then 😉

Categories: Magiq

Magiq-to-NHibernate: Collection filtering and moving to NHibernate 3

February 25, 2010 1 comment

Few days ago I started having troubles with Linq-to-NHibernate from the current release 2.1.2. The main problem cames when I design the collection filtering strategy. Basically, my idea was to go from:

parent.ChildCollection

to:

session.Linq<Child>().Single( x=>x.Id == parent.Id ).SelectMany( x=>x.ChildCollection );

Having this, we could add many expressions to that queryable as we want.

The thing is, as Chadly posted, Linq-to-nhibernate 1.0 uses the query parameter (the x in the previous expression) as the criteria alias, so this works:

session.Linq<Child>()
       .Single( x=>x.Id == parent.Id )
       .SelectMany( x=>x.ChildCollection, (p,x) => x )
       .Where( x => x.Something );

but this doen’t:

session.Linq<Child>()
       .Single( x=>x.Id == parent.Id )
       .SelectMany( x=>x.ChildCollection, (p,x) => x )
       .Where( z => z.Something );

Since the chosen strategy for dynamically generating the query involved the definition of the “alias” parameter, and the user will need to know which is, I gave up. So I tried NHibernate 3. And it worked 🙂

It was really painful to change what I’ve done for the old linq provider, because it uses criteria and the new one uses hql. It’s not easy at all to get a IDbCommand from a HQL, but not impossible.

By now, deletes, updates, inserts and bulkinserts are working properly for linq-to-nhibernate 2.0 with the same limitation as before: no inheritance, no collections.
In the next days I will be working on collection support, composite ids and mappings.