(0) exportieren Drucken
Alle erweitern
Erweitern Minimieren

Kompilierte Abfragen (LINQ to Entities)

Wenn eine Anwendung im Entity Framework häufig strukturell ähnliche Abfragen ausführt, kann in vielen Fällen die Leistung gesteigert werden, indem die Abfrage einmal kompiliert und anschließend mehrmals mit verschiedenen Parametern ausgeführt wird. So können beispielsweise mithilfe einer Anwendung alle Kunden in einer bestimmten Stadt abgerufen werden, wobei die Stadt zur Laufzeit vom Benutzer in einem Formular festgelegt wird. Für derartige Aufgaben unterstützt LINQ to Entities die Verwendung kompilierter Abfragen.

Die CompiledQuery-Klasse ermöglicht das Kompilieren und Zwischenspeichern von Abfragen zur Wiederverwendung. Diese Klasse enthält eine Compile-Methode einer CompiledQuery mit mehreren Überladungen. Rufen Sie die Compile-Methode auf, um einen neuen Delegaten für die Darstellung der kompilierten Abfrage zu erstellen. Die mit einem ObjectContext und Parameterwerten ausgestatteten Compile-Methoden geben einen Delegat zurück, der ein Ergebnis ausgibt (z. B. eine IQueryable-Instanz). Die Abfrage wird nur einmal während der ersten Ausführung kompiliert. Die für die Abfrage zur Kompilierungszeit festgelegten Zusammenführungsoptionen können später nicht geändert werden. Nachdem die Abfrage kompiliert ist, können Sie nur Parameter vom primitiven Typ angeben. Sie können jedoch keine Teile der Abfrage ersetzen, die das generierte SQL ändern.

Der LINQ to Entities -Abfrageausdruck, der von der Compile-Methode der CompiledQuery kompiliert wird, wird durch einen der generischen Func-Delegaten dargestellt wird, z. B. Func. Der Abfrageausdruck kann höchstens einen ObjectContext-Parameter, einen Rückgabeparameter und 16 Abfrageparameter kapseln. Sind mehr als 16 Abfrageparameter erforderlich, können Sie eine Struktur erstellen, deren Eigenschaften Abfrageparameter darstellen. Sie können anschließend die Eigenschaften für die Struktur im Abfrageausdruck verwenden, nachdem die Eigenschaften festgelegt wurden.

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, die einen Decimal-Eingabeparameter akzeptiert und eine Auftragssequenz zurückgibt, in der der fällige Gesamtbetrag 200,00 US-Dollar oder mehr beträgt:

static readonly Func<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery2 = 
    CompiledQuery.Compile<AdventureWorksEntities, Decimal, IQueryable<SalesOrderHeader>>(
            (ctx, total) => from order in ctx.SalesOrderHeaders
                            where order.TotalDue >= total
                            select order);

static void CompiledQuery2()
{            
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        Decimal totalDue = 200.00M;

        IQueryable<SalesOrderHeader> orders = s_compiledQuery2.Invoke(context, totalDue);

        foreach (SalesOrderHeader order in orders)
        {
            Console.WriteLine("ID: {0}  Order date: {1} Total due: {2}",
                order.SalesOrderID,
                order.OrderDate,
                order.TotalDue);
        }
    }            
}

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, die eine ObjectQuery-Instanz zurückgibt:

static readonly Func<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>> s_compiledQuery1 = 
    CompiledQuery.Compile<AdventureWorksEntities, ObjectQuery<SalesOrderHeader>>(
            ctx => ctx.SalesOrderHeaders);

static void CompiledQuery1_MQ()
{
    
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        IQueryable<SalesOrderHeader> orders = s_compiledQuery1.Invoke(context);

        foreach (SalesOrderHeader order in orders)
            Console.WriteLine(order.SalesOrderID);
    }            
}

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, die den Durchschnitt der Produktlistenpreise als Decimal-Wert zurückgibt:

static readonly Func<AdventureWorksEntities, Decimal> s_compiledQuery3MQ = CompiledQuery.Compile<AdventureWorksEntities, Decimal>(
            ctx => ctx.Products.Average(product => product.ListPrice));

static void CompiledQuery3_MQ()
{
    
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        Decimal averageProductPrice = s_compiledQuery3MQ.Invoke(context);

        Console.WriteLine("The average of the product list prices is $: {0}", averageProductPrice);
    }            
}

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, der ein String-Eingabeparameter übergeben wird und die einen Contact zurückgibt, dessen E-Mail-Adresse mit der angegebenen Zeichenfolge beginnt:

static readonly Func<AdventureWorksEntities, string, Contact> s_compiledQuery4MQ = 
    CompiledQuery.Compile<AdventureWorksEntities, string, Contact>(
            (ctx, name) => ctx.Contacts.First(contact => contact.EmailAddress.StartsWith(name)));

static void CompiledQuery4_MQ()
{            
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        string contactName = "caroline";
        Contact foundContact = s_compiledQuery4MQ.Invoke(context, contactName);

        Console.WriteLine("An email address starting with 'caroline': {0}",
            foundContact.EmailAddress);
    }            
}

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, der ein DateTime-Eingabeparameter und ein Decimal-Eingabeparameter übergeben wird und die eine Sequenz von Aufträgen zurückgibt, in denen das Auftragsdatum nach dem 3. März 2008 liegt und der fällige Gesamtbetrag weniger als 300,00 Dollar beträgt:

static readonly Func<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>> s_compiledQuery5 = 
    CompiledQuery.Compile<AdventureWorksEntities, DateTime, Decimal, IQueryable<SalesOrderHeader>>(
            (ctx, orderDate, totalDue) => from product in ctx.SalesOrderHeaders
                                          where product.OrderDate > orderDate 
                                             && product.TotalDue < totalDue
                                          orderby product.OrderDate
                                          select product);

static void CompiledQuery5()
{            
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {         
        DateTime date = new DateTime(2003, 3, 8);
        Decimal amountDue = 300.00M;

        IQueryable<SalesOrderHeader> orders = s_compiledQuery5.Invoke(context, date, amountDue);

        foreach (SalesOrderHeader order in orders)
        {
            Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue);
        }
    }            
}

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, der ein DateTime-Eingabeparameter übergeben wird und die eine Sequenz von Aufträgen zurückgibt, in denen das Bestelldatum nach dem 8. März 2004 liegt: Diese Abfrage gibt die Bestellinformationen als Sequenz anonymer Typen zurück. Anonyme Typen werden vom Compiler abgeleitet, sodass in der Compile-Methode von CompiledQuery keine Typenparameter angegeben werden können. Der Typ wird in der Abfrage selbst definiert.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    var compiledQuery = CompiledQuery.Compile((AdventureWorksEntities ctx, DateTime orderDate) =>
        from order in ctx.SalesOrderHeaders
        where order.OrderDate > orderDate
        select new {order.OrderDate, order.SalesOrderID, order.TotalDue});

    DateTime date = new DateTime(2004, 3, 8);
    var results = compiledQuery.Invoke(context, date);

    foreach (var order in results)
    {
        Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", order.SalesOrderID, order.OrderDate, order.TotalDue);
    }
}

Beispiel

Im folgenden Beispiel wird eine Abfrage kompiliert und anschließend aufgerufen, die einen Eingabeparameter mit einer benutzerdefinierten Struktur akzeptiert und eine Sequenz von Aufträgen zurückgibt. Die Struktur definiert die Parameter für das Startdatum, das Enddatum und die fällige Gesamtbetragsabfrage. Die Abfrage gibt die zwischen dem 3. und 8. März 2003 gelieferten Bestellungen mit einem fälligen Gesamtbetrag von über 700,00 US-Dollar zurück.

static Func<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>> s_compiledQuery = 
    CompiledQuery.Compile<AdventureWorksEntities, MyParams, IQueryable<SalesOrderHeader>>(
            (ctx, myparams) => from sale in ctx.SalesOrderHeaders
                               where sale.ShipDate > myparams.startDate && sale.ShipDate < myparams.endDate 
                               && sale.TotalDue > myparams.totalDue  
                               select sale);
static void CompiledQuery7()
{
    
    using (AdventureWorksEntities context = new AdventureWorksEntities())
    {
        MyParams myParams = new MyParams();
        myParams.startDate = new DateTime(2003, 3, 3);
        myParams.endDate = new DateTime(2003, 3, 8);
        myParams.totalDue = 700.00M;

        

        IQueryable<SalesOrderHeader> sales = s_compiledQuery.Invoke(context, myParams);

        foreach (SalesOrderHeader sale in sales)
        {
            Console.WriteLine("ID: {0}", sale.SalesOrderID);
            Console.WriteLine("Ship date: {0}", sale.ShipDate);
            Console.WriteLine("Total due: {0}", sale.TotalDue);
        }
    }            
}

Die Struktur, die die Abfrageparameter definiert:

struct MyParams
{
    public DateTime startDate;
    public DateTime endDate;
    public decimal totalDue;
}

Siehe auch

Community-Beiträge

HINZUFÜGEN
Anzeigen:
© 2014 Microsoft