LINQ-Erweiterungen für Azure Table Storage implementieren oder und enthalten

    Hallo allerseits! Ich freue mich, Ihnen den fünften Artikel aus der Reihe „Internes Gerät und Architektur des AtContent.com-Dienstes“ vorstellen zu können. In diesem Artikel werde ich erläutern, wie Sie die Arbeit mit Azure Table Storage funktionaler und komfortabler gestalten können.

    LINQ

    Die Windows Azure-Plattform bietet eine Reihe leistungsstarker Tools zur Implementierung Ihrer Ideen. Und darunter - Azure Table Storage - eine nicht relationale Datenbank mit unbegrenzter Menge. Ein großer Vorteil dieses Speichers besteht darin, dass Sie sehr komplexe Abfragen durchführen können. Abgesehen davon gibt es einige Unannehmlichkeiten. Mit LINQ können Sie beispielsweise keine Abfragen mit der Logik "Oder" oder "Enthält" ohne zusätzliche Änderungen ausführen.

    Als wir uns dem stellen mussten, untersuchten wir das Problem und es stellte sich heraus, dass Sie mit Hilfe der REST-API Anfragen stellen können, die Or haben. Und wir brauchten solche Anfragen wirklich. Schreiben Sie jetzt nicht den gesamten Code von LINQ in die REST-API. Wir gruben ein wenig tiefer und fanden eine Lösung!

    Um eine bequeme Arbeitsweise mit Azure Table Storage - LINQ - beizubehalten und die Möglichkeit zu ergänzen, Contains-Abfragen zu erstellen, mussten die Mechanismen analysiert werden, die in den Tiefen von LINQ auftreten, wenn eine Abfrage in eine REST-API umgewandelt wird. Das Problem selbst ist, dass wir die LINQ-Abfrage nur mit Where dynamisch ändern konnten. In diesem Fall wird der Ausdruck mit dem And-Modifikator zur Anforderung hinzugefügt. Daher ist es nicht schwierig, eine Abfrage mit einer variablen Anzahl von Parametern durchzuführen, die durch den Operator "Und" verbunden sind. Wenn Sie dasselbe für Or tun müssen, müssen Sie Lambda-Ausdrücke verwenden, um zu helfen.

    Natürlich können Sie einfach mehrere Anfragen stellen und diese dann zu einer kombinieren. Diese Verschwendung wirkt sich jedoch negativ auf die endgültigen Kosten der Lösung für Ihre Kunden oder Abonnenten aus. Selbst bei den Kosten einer Anfrage in Hundertstel Cent ist der Unterschied zwischen einer Anfrage und beispielsweise zehn offensichtlich. Deshalb wenden wir uns unserer Entscheidung zu.

    Der erste Versuch schlug fehl. Suchmaschinen konnten in dieser Angelegenheit nicht weiterhelfen und mussten daher experimentell vorgehen. In IQuerable.Where () können Sie Expression ersetzen>. Ich war enttäuscht, nachdem ich einen solchen Ausdruck mit Kummer in zwei Hälften gemacht und getestet hatte. Der resultierende Ausdruck nach Invoke () enthielt Klassennamen, und eine solche Abfrage an Azure Table Storage gab mit Sicherheit eine Ausnahme zurück.

    Das hat mich aber nicht aufgehalten. Die Aussicht, eine REST-API anstelle von LINQ zu verwenden, hat mich wach gehalten. Nur ein paar Tage intensives Lesen von MSDN und eine elegante Lösung entstanden, die sehr einfach anzuwenden ist.

    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;
        }
    }
    

    Hiermit können Sie die Contains-Operation auf die Anforderung anwenden. Somit wird ein Analogon der IN-Operation in SQL erhalten. Dies hat die Anwendbarkeit von Azure Table Storage in unserem Projekt erheblich erweitert.

    In dieser Implementierung sollte beachtet werden, dass der Lambda-Ausdruck schrittweise aufgebaut ist und die Zeile, die mich für ein paar Tage nicht einschlafen ließ, wie folgt aussieht:
    ConstantExpression ValueConst = Expression.Constant(ValueToCompare, typeof(string));
    

    Sie gibt an, dass beim Ausführen von invoke () die Konstante und nicht der Wert des Objekts ersetzt werden muss.
    Die hier angegebene Implementierung kann nur mit Zeichenfolgenwerten arbeiten, aber nichts hindert Sie daran, diese Methoden für die Verwendung mit beliebigen Typen selbst zu erweitern.

    Die in diesem Artikel beschriebene Lösung ist Teil der CPlase Open Source-Bibliothek, die zur Veröffentlichung vorbereitet wird.

    Lesen Sie in der Reihe:

    Ich lade Sie auch ein, unseren Service zu testen
    Atcontent

    Jetzt auch beliebt: