Home .NET LINQ extensions for Azure Table Storage, implementing Or and Contains

LINQ extensions for Azure Table Storage, implementing Or and Contains

by admin

Hi all, I am pleased to present you the fifth article in the series "The internal structure and architecture of the AtContent.com service". In it I will tell you how to make working with Azure Table Storage more functional and convenient.
LINQ extensions for Azure Table Storage, implementing Or and Contains
The Windows Azure platform gives you a very powerful set of tools to implement your ideas. And among them is Azure Table Storage, a non-relational database with unlimited capacity. The big advantage of this storage is that you can make quite complex queries to it. But apart from that, there are some disadvantages. For example, with LINQ, you can’t make queries that have Or or Contains logic without additional modifications.
When we encountered this problem, we investigated the problem and found out that you can make requests with Or using REST API. And we really needed such requests. We wouldn’t need to rewrite all of our code from LINQ to the REST API for this. So we dug a little deeper and found a solution!
So, in order to keep Azure Table Storage’s handy way of working – LINQ – and supplement it with the ability to do Contains-queries, we needed to break down the mechanisms that take place in the depths of LINQ when transforming a query into a REST API. The problem is that we can dynamically modify a LINQ request only with the help of Where. In this case the expression is added to the query with the modifier And. Therefore it is not difficult to write a query with a variable number of parameters, connected by the And operator. If you need to do the same for Or, you will have to use lambda expressions.
Sure, you can simply make multiple queries and then combine them into one, but such wastefulness has a negative impact on the final cost of the solution to your customers or subscribers. Even at a cost of a hundredth of a cent per query, the difference between one query and, say, ten is obvious. So let’s move on to our solution.
The first attempt ended in failure. The search engines couldn’t help in this matter, so I had to act by experiment. In IQuerable.Where() you can substitute Expression<Func<T, bool> > . After having miserably composed such an expression and tried it out, I was disappointed. The resulting expression after Invoke() included class names and this query to Azure Table Storage certainly returned an exception.
But that didn’t stop me. The prospect of using the REST API instead of LINQ kept me awake. Just a couple of days of intensive reading of MSDN and an elegant solution was born which can be applied very easily.

public static class LinqExtension{public static Expression<Func<T, bool> > Contains<T> (string ObjectStringName, string FieldStringNameToCompare, IList<String> ListOfValues){Expression ExprBody = null;ParameterExpression ParameterObject = Expression.Parameter(typeof(T), ObjectStringName);var PropertyFieldToCompare = Expression.Property(ParameterObject, FieldStringNameToCompare);foreach (var ValueToCompare in ListOfValues){ConstantExpression ValueConst = Expression.Constant(ValueToCompare, typeof(string));BinaryExpression EqualTermExpression = Expression.Equal(PropertyFieldToCompare, ValueConst);if (ExprBody == null) { ExprBody = EqualTermExpression; }else{ExprBody = Expression.Or(ExprBody, EqualTermExpression);}}if (ExprBody == null){ExprBody = Expression.IsTrue(Expression.Constant(false));}var FinalExpression = Expression.Lambda<Func<T, bool> > (ExprBody, new ParameterExpression[] { ParameterObject });return FinalExpression;}public static IQueryable<T> Contains<T> (this IQueryable<T> obj, string ObjectStringName, string FieldStringNameToCompare, IList<String> ListOfValues){var Expression = Contains<T> (ObjectStringName, FieldStringNameToCompare, ListOfValues);if (Expression != null)return obj.Where<T> (Expression);return obj;}}

It allows you to apply a Contains operation to a query. This gives you an analog to the IN operation in SQL. This greatly expanded the applicability of Azure Table Storage in our project.
In this implementation it should be noted that the lambda-expression is constructed in stages and the very line that kept me awake for a couple of days looks like this :

ConstantExpression ValueConst = Expression.Constant(ValueToCompare, typeof(string));

This is the one that specifies that when you do Invoke(), you should substitute a constant, not an object value.
The implementation given here can only work with string values, but nothing prevents you from extending these methods yourself to apply to any types.
The solution described in this article is part of the Open Source CPlase library which is about to be published.
Read in the series :

You are also welcome to try our service
LINQ extensions for Azure Table Storage, implementing Or and Contains

You may also like