Zur Zeit wird gefiltert nach: esql
Filter zurücksetzen

Entity Framework 4 - Die Eigenschaft Contains unterstützt Arrays

Was in Linq to SQL kein Problem darstellte, ist im Entity Framework 1 eine kleine Herausforderung. Allein deswegen habe ich mich mit Entity SQL (eSQL) auseinandergesetzt.

Der Ablauf war sehr einfach. Bei der Abfrage konnte man nach dem Inhalt eines Arrays suchen lassen und bekam das Resultat von der Datenquelle zurück. Der Code dafür ist leicht verständlich.

C#
int[] valueArray = new int[] { 3, 4, 5, 9 };

var result = from d in context.Dispatchings
                 where valueArray.Contains(d.diAutoID)
                 select d;

Meine Erwartung, bedingt durch Linq to SQL, konnte EF1 nicht erfüllen. Statt eines Ergebnisses wird eine NotSupportedException erzeugt.

Abbildung 1
Abbildung 1: NotSupportedException in EF1

Neben eSQL gibt es für das Entity Framework einen Workaround, der ein schreckliches OR-Konstrukt an die Datenquelle sendet und auch noch so heisst: BuildOrExpression.

C# (Workaround BuldOrExpression)
    public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(
            Expression<Func<TElement, TValue>> valueSelector,
            IEnumerable<TValue> values
        )
    {
      if (null == valueSelector)
        throw new ArgumentNullException("valueSelector");

      if (null == values)
        throw new ArgumentNullException("values");

      ParameterExpression p = valueSelector.Parameters.Single();

      if (!values.Any())
        return e => false;

      var equals = values.Select(value =>
          (Expression)Expression.Equal(
               valueSelector.Body,
               Expression.Constant(
                   value,
                   typeof(TValue)
               )
          )
      );

      var body = equals.Aggregate(
               (accumulate, equal) => Expression.Or(accumulate, equal)
       );

      return Expression.Lambda<Func<TElement, bool>>(body, p);
    }

Im Code konnte dieser Ausdruck nur in Lamda-Ausdrücken verwendet werden. In der Linq-Syntax habe ich diesen Workaround nie zum laufen gebracht.

C# (Einsatz BuildOrExpression)
int[] valueArray = new int[] { 3, 4, 5, 9 };

var result = context.Dispatchings.Where(
      EfExtensions.BuildOrExpression<Dispatching,int>
       (v => v.diAutoID, valueArray)
);

Im Entity Framework 4 sind diese Spielereien nicht mehr notwendig. Die Array-Unterstützung der Eigenschaft IEnumerable.Contains trägt auch dazu bei, dass der Code verständlicher wird.

C# (Abfrage in EF4)
var result = from d in context.Dispatchings
                   where valueArray.Contains(d.diAutoID)
                   select d;

Ehrlich, der Code sieht doch viel besser aus, wenn man die Eigenschaftsnamen aussen vor lässt.

Good bye BuildOrExpression!

Zurück

Entity Framework 4 - Aus IN wird IN

So banal der Titel auch klingt, das Entity Framework in der ersten Version konnte den SQL-Operator IN nicht erzeugen. Interessanterweise gibt es den Mengenoperator IN im Entity SQL, aber zur Datenbank wurde ein OR - Konstrukt abgesetzt. Zum Glück ist der SQL-Server in der Lage solche hässlichen SQL-Abfragen zu optimieren.

Abbildung 1
Abbildung 1: Ausführungsplan Gegenüberstellung OR-Konstrukt mit Mengenoperator IN

Wer jetzt denkt wo ist das Problem, der kennt den Oracle-Server nicht. Oracle verzeiht solche schrecklichen Abfragen in der Regel nicht. Um in Oracle Abfragen mit OR–Konstrukten zu optimieren, steht der Hint USE_CONCAT zur Verfügung. Diesen mit dem Entity Framework zu benutzen, erweist sich aber als schwierig. Hinzu kommt, dass Microsoft für andere Datenbanken keine Provider anbieten wird.

Wie gross der Text der erzeugten SQL-Abfrage sein kann, habe ich noch nicht gefunden, eine Testabfrage erzeugte in meiner Umgebung ca. 45‘000 Zeichen und die konnte problemlos zum SQL-Server gesendet und verarbeitet werden.

In diesem Beitrag will ich mich dem Mengenoperator IN im eSQL widmen, da auch die Meinung vertreten wird, dass IN nicht vom Entity Framework unterstützt würde. Die letzte Konferenz, auf der ich diese Aussage hörte, war die Basta Spring.

Der Ausführungsplan ist bereits in Abbildung 1 zu sehen, nachfolgend ist der eSQL-Ausdruck für den Mengenoperator IN und die SQL-Abfrage die in der .NET 3.5-Umgebung abgesetzt wird.

eSQL
SELECT VALUE p.diAutoID FROM TestModel35.Dispatchings AS p
WHERE p.diAutoID IN { 1,2,3,4,5,6,7,8 }

T-SQL (erzeugt von EF1)
SELECT 
[Extent1].[diAutoID] AS [diAutoID]
FROM [dbo].[tbDispatching] AS [Extent1]
WHERE ([Extent1].[diAutoID] = 1) OR ([Extent1].[diAutoID] = 2) 
OR ([Extent1].[diAutoID] = 3) OR ([Extent1].[diAutoID] = 4) 
OR ([Extent1].[diAutoID] = 5) OR ([Extent1].[diAutoID] = 6) 
OR ([Extent1].[diAutoID] = 7) OR ([Extent1].[diAutoID] = 8)

Im Entity Framework 4 ändert sich an der eSQL-Syntax nichts. Der einzige Unterschied liegt im erzeugten SQL-Code.

T-SQL (erzeugt von EF4)
SELECT 
[Extent1].[diPlanAutoID] AS [diPlanAutoID]
FROM [dbo].[tbDispatching] AS [Extent1]
WHERE [Extent1].[diAutoID] IN (1,2,3,4,5,6,7,8)

Dieses Beispiel zeigt schön, dass im Entity Framework 4 auch unter der Haube - am SQL-Code - gearbeitet wurde. In diesem Bereich wird vor allem der Administrator aufatmen können.

Zurück

Translate this page

Kategorien

  • [-].NET Development (215)
  • [-]Datenbank (26)
  • HTML (1)
  • Konfiguration (12)
  • Mind Map (10)
  • Off-topic (9)
  • Open Source (3)
  • Qualität (7)
  • Sharepoint (6)
  • Sicherheit (2)

Archiv

Social Bookmarking

Bookmark bei: Mr. Wong Bookmark bei: Webnews Bookmark bei: Icio Bookmark bei: Oneview Bookmark bei: Linkarena Bookmark bei: Favoriten Bookmark bei: Seekxl Bookmark bei: Favit Bookmark bei: Social Bookmarking Tool Bookmark bei: Power Oldie Bookmark bei: Bookmarks.cc Bookmark bei: Newskick Bookmark bei: Newsider Bookmark bei: Linksilo Bookmark bei: Readster Bookmark bei: Folkd Bookmark bei: Yigg Bookmark bei: Digg Bookmark bei: Del.icio.us Bookmark bei: Reddit Bookmark bei: Simpy Bookmark bei: StumbleUpon Bookmark bei: Slashdot Bookmark bei: Netscape Bookmark bei: Furl Bookmark bei: Yahoo Bookmark bei: Spurl Bookmark bei: Google Bookmark bei: Blinklist Bookmark bei: Blogmarks Bookmark bei: Diigo Bookmark bei: Technorati Bookmark bei: Newsvine Bookmark bei: Blinkbits Bookmark bei: Ma.Gnolia Bookmark bei: Smarking Bookmark bei: Netvouz Information