Monthly Archives: March 2012

Shorter Firebird queries from Entity Framework

Yesterday I released ADO.NET provider for Firebird version 2.7.5 and there’s one feature I’d like to blog about. As you might know Firebird has a pretty old limitation on “size” of query. It’s both the string itself, but also the column datatypes and parameters used. No need to dive to details, because I’ll only talk about the first item.

When you’re using Entity Framework (or any other ORM) the query is generated by machine. And the machine (or maybe better to say algorithm) needs to be sure, that in every case the query is correct. That’s the reason why you see a lot braces even if it’s not needed in your case. A lot of table aliases, escaping, quoting and so on. It’s not a simple task. But all these extra characters are making the query bigger. Consider that the the generated query isn’t always the shortest (you could write it shorter because either you have some out-of-band knowledge about you database or simply because there’s room for improvement) and all this “character noise” and you might hit the query length limit.

In the above mentioned version I made some improvements to table aliases. Instead of using full names from Entity Framework, I’m trying to use one character names (or +1, +2, +3, … if I run out of 1, 2, 3, … character names). So instead of (example)

select Extent1.Foo, Extent1.Bar, Extent2.Baz from SomeTable as Extent1 join AnotherTable as Extent2 ...

you’ll get

select A.Foo, A.Bar, B.Baz from SomeTable as A join AnotherTable as B ...

Nothing super-cool, but because somebody suggested this in tracker, it’s there. On the other hand to be honest I’ve never hit the query length limit myself. Maybe I’m lucky, maybe I’m writing too simple queries. But still, shorter query means also less data to be transfered. Hope to help to use Entity Framework and Firebird for big stuff. :)

ADO.NET provider for Firebird 2.7.5 released

The 2.7.5 version of ADO.NET provider for Firebird is ready for download. This version contains mainly bug fixes (some pretty nasty) resulting in stability improvements.

You can check the tracker for more details about this release and of course download it from website or NuGet.

Enjoy!

Include with filtering or limiting

Almost four years ago I wrote an article Load with filtering or limiting. You might want to do same stuff with Include method. It’s not directly supported in this method but you can do it with anonymous object easily. There’s only one catch, it’s the anonymous object. That means, if you need the entities you need to manually select these out on IEnumerable<T> (doing it on query isn’t going to work because Entity Framework will (correctly) figure out you’re not using the pieces of anonymous object and will change the generated query appropriately).

Small example:

context.EntitySet
	.Select(x => new { Entity = x, Related = x.Related.OrderBy(y => y.FooBar).Take(6) })
	.AsEnumerable()
	.Select(x => x.Entity)
	.ToArray();

Nothing fancy. But could it be wrapped inside method so you don’t have to type it over and over again. In comments of above mentioned post same question was raised. Well if I can write it manually, why it shouldn’t be possible to extract it into method, right? Don’t know whether this method has any real usage, but it was a nice exercise.

public static IEnumerable<TMain> Include2<TMain, TOther>(this IQueryable<TMain> source, Expression<Func<TMain, IEnumerable<TOther>>> path)
	where TMain : class
{
	TMain main = default(TMain);
	var dummy = new { Main = main, Included = Enumerable.Empty<TOther>() };
	Expression<Func<TMain, object>> exampleExpression = x => new
	{
		Main = x,
		Included = Enumerable.Empty<TOther>()
	};
	PropertyInfo mainProperty = dummy.GetType().GetProperty("Main");
	ParameterExpression accessParam = Expression.Parameter(dummy.GetType(), "x");
	Delegate mainBack = Expression.Lambda(Expression.MakeMemberAccess(accessParam, mainProperty), accessParam).Compile();

	NewExpression body = (exampleExpression.Body as NewExpression);
	Type anonymousType = body.Type;

	var parametersMap = exampleExpression.Parameters.Select((f, i) => new { f, s = path.Parameters[i] }).ToDictionary(p => p.s, p => p.f);
	Expression reboundBody = ParameterRebinder.ReplaceParameters(parametersMap, path.Body);
	NewExpression newExpression = body.Update(new[] { body.Arguments[0], reboundBody });
	LambdaExpression finalLambda = Expression.Lambda(newExpression, exampleExpression.Parameters);

	MethodInfo miA = typeof(Queryable).GetMethods()
		.Where(m => m.Name == "Select")
		.Where(m => m.GetParameters()[1].ParameterType.GetGenericArguments()[0].GetGenericArguments().Count() == 2)
		.First();
	MethodInfo miB = typeof(Enumerable).GetMethods()
		.Where(m => m.Name == "Select")
		.Where(m => m.GetParameters()[1].ParameterType.GetGenericArguments().Count() == 2)
		.First();

	MethodInfo selectAMethod = miA.MakeGenericMethod(typeof(TMain), anonymousType);
	var dataA = selectAMethod.Invoke(null, new object[] { source, finalLambda });

	MethodInfo selectBMethod = miB.MakeGenericMethod(anonymousType, typeof(TMain));
	var dataB = selectBMethod.Invoke(null, new object[] { dataA, mainBack });

	return dataB as IEnumerable<TMain>;
}

The method is doing little bit of magic with expressions and anonymous type to do what you would normally write by hand. It returns IEnumerable<T> because the object needs to be unwrapped locally so you can’t add additional pieces into query. I’m using ParameterRebinder from Colin Meek’s post to properly rewire parameters. Same functionality can be also found in Mono.Linq.Expressions.

From input parameters types (yeah, the power of static typing [Anders Hejlsberg]) you can see how to use it:

context.EntitySet
	.Include2(x => x.Related.OrderBy(y => y.FooBar).Take(6))
	.ToArray();

That’s all. 8-)