LINQ Extensions for Azure Table Storage Implementing Or and Contains

    Hello! I am pleased to present to you the fifth article in the series “Internal structure and architecture of AtContent.com service”. In it, I’ll talk about how to make working with Azure Table Storage more functional and convenient.

    LINQ

    The Windows Azure platform provides a very powerful set of tools to implement your ideas. And among them - Azure Table Storage - a non-relational database with an unlimited amount. A big plus of this storage is that you can make quite complex queries to it. But besides this there are some inconveniences. So, for example, with LINQ, you cannot run queries that have the logic Or or Contains without additional modifications.

    When we had to face this, we studied the problem and it turned out that with the help of the REST API you can make requests that have Or. And we really needed such requests. Do not now rewrite all the code from LINQ to the REST API for this. Digging a little deeper, we found a solution!

    So, in order to maintain a convenient way to work with Azure Table Storage - LINQ - and to complement its ability to make Contains queries, it was necessary to parse the mechanisms that occur in the depths of LINQ when transforming a query into a REST API. The problem itself is that we only managed to dynamically modify the LINQ query with Where. In this case, the expression is added to the request with the And modifier. Therefore, making a query with a variable number of parameters connected by the And operator is not difficult. If you need to do the same for Or, you have to use lambda expressions to help.

    Of course, you can simply make several requests and then combine them into one, but such wastefulness negatively affects the final cost of the solution for your customers or subscribers. Even with the cost of one request in hundredths of a cent, the difference between one request and, say, ten is obvious. Therefore, we will move on to our decision.

    The first attempt failed. Search engines could not help in this matter and therefore had to act through experiment. In IQuerable.Where (), you can substitute Expression>. Having made such an expression with grief in half and having tested it, I was disappointed. The resulting expression after Invoke () included class names, and such a query to Azure Table Storage certainly returned an exception.

    But that did not stop me. The prospect of using a 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 very simple to apply.

    public static class LinqExtension
    {
        public static Expression> Contains(string ObjectStringName, string FieldStringNameToCompare, IList 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>(ExprBody, new ParameterExpression[] { ParameterObject });
            return FinalExpression;
        }
        public static IQueryable Contains(this IQueryable obj, string ObjectStringName, string FieldStringNameToCompare, IList ListOfValues)
        {
            var Expression = Contains(ObjectStringName, FieldStringNameToCompare, ListOfValues);
            if (Expression != null)
                return obj.Where(Expression);
            return obj;
        }
    }
    

    It allows you to apply the Contains operation to the request. Thus, an analogue of the IN operation in SQL is obtained. This has 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 did not let me fall asleep for a couple of days looks like this:
    ConstantExpression ValueConst = Expression.Constant(ValueToCompare, typeof(string));
    

    It is she who indicates that when invoke () is executed, the constant must be substituted, not the value of the object.
    The implementation given here can only work with string values, but nothing prevents you from expanding these methods yourself for use with any types.

    The solution described in the article is included in the Open Source CPlase library, which is being prepared for publication.

    Read in the series:

    I also invite you to try our service
    Atcontent

    Also popular now: