Derlenmiş sorgular (LINQ to Entities)

Entity Framework'te yapısal olarak benzer sorguları birçok kez yürüten bir uygulamanız olduğunda, sorguyu bir kez derleyip farklı parametrelerle birkaç kez yürüterek performansı sık sık artırabilirsiniz. Örneğin, bir uygulamanın belirli bir şehirdeki tüm müşterileri alması gerekebilir; şehir, kullanıcı tarafından çalışma zamanında bir formda belirtilir. LINQ to Entities, bu amaçla derlenmiş sorguların kullanılmasını destekler.

.NET Framework 4.5'den başlayarak LINQ sorguları otomatik olarak önbelleğe alınır. Ancak, daha sonraki yürütmelerde bu maliyeti azaltmak için derlenmiş LINQ sorgularını kullanmaya devam edebilirsiniz ve derlenmiş sorgular otomatik olarak önbelleğe alınan LINQ sorgularından daha verimli olabilir. işleci bellek içi koleksiyonlara uygulayan Enumerable.Contains LINQ to Entities sorguları otomatik olarak önbelleğe alınmaz. Ayrıca, derlenmiş LINQ sorgularında bellek içi koleksiyonları parametreleştirmeye izin verilmez.

sınıfı, CompiledQuery yeniden kullanmak üzere sorguların derlenmesini ve önbelleğe alınmasını sağlar. Kavramsal olarak, bu sınıf birkaç aşırı yükleme ile bir CompiledQuery's Compile yöntemi içerir. Derlenen sorguyu Compile temsil eden yeni bir temsilci oluşturmak için yöntemini çağırın. Compile ve parametre değerleriyle sağlanan ObjectContext yöntemler, bazı sonuçlar (örneğin, bir örnek) üreten bir IQueryable<T> temsilci döndürür. Sorgu yalnızca ilk yürütme sırasında bir kez derlenmiş olur. Derleme sırasında sorgu için ayarlanan birleştirme seçenekleri daha sonra değiştirilemez. Sorgu derlendiğinde yalnızca ilkel türde parametreler sağlayabilirsiniz, ancak sorgunun oluşturulan SQL'i değiştirecek bölümlerini değiştiremezsiniz. Daha fazla bilgi için bkz . EF Birleştirme Seçenekleri ve Derlenmiş Sorgular.

'nin Compile yönteminin CompiledQueryderlediği LINQ to Entities sorgu ifadesi gibi Func<T1,T2,T3,T4,TResult>genel Func temsilcilerden biri tarafından temsil edilir. Sorgu ifadesi en fazla bir ObjectContext parametreyi, dönüş parametresini ve 16 sorgu parametresini kapsülleyebilir. 16'dan fazla sorgu parametresi gerekiyorsa, özellikleri sorgu parametrelerini temsil eden bir yapı oluşturabilirsiniz. Ardından, özellikleri ayarladıktan sonra sorgu ifadesindeki yapıdaki özellikleri kullanabilirsiniz.

Örnek 1

Aşağıdaki örnek, giriş parametresini kabul eden bir Decimal sorguyu derleyip çağırır ve toplam ödemenin 200,00 TL'den büyük veya buna eşit olduğu bir sipariş dizisi döndürür:

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);
        }
    }
}
ReadOnly s_compQuery2 As Func(Of AdventureWorksEntities, Decimal, IQueryable(Of SalesOrderHeader)) = _
    CompiledQuery.Compile(Of AdventureWorksEntities, Decimal, IQueryable(Of SalesOrderHeader))( _
                Function(ctx As AdventureWorksEntities, total As Decimal) _
                    From order In ctx.SalesOrderHeaders _
                    Where (order.TotalDue >= total) _
                    Select order)

Sub CompiledQuery2()
    Using context As New AdventureWorksEntities()

        Dim totalDue As Decimal = 200.0

        Dim orders As IQueryable(Of SalesOrderHeader) = s_compQuery2.Invoke(context, totalDue)

        For Each order In orders
            Console.WriteLine("ID: {0}  Order date: {1} Total due: {2}", _
                                    order.SalesOrderID, _
                                    order.OrderDate, _
                                    order.TotalDue)
        Next
    End Using
End Sub

Örnek 2

Aşağıdaki örnek, bir örneği döndüren ObjectQuery<T> bir sorguyu derleyip çağırır:

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);
    }
}
ReadOnly s_compQuery1 As Func(Of AdventureWorksEntities, ObjectQuery(Of SalesOrderHeader)) = _
    CompiledQuery.Compile(Of AdventureWorksEntities, ObjectQuery(Of SalesOrderHeader))( _
                Function(ctx) ctx.SalesOrderHeaders)

Sub CompiledQuery1_MQ()

    Using context As New AdventureWorksEntities()

        Dim orders As ObjectQuery(Of SalesOrderHeader) = s_compQuery1.Invoke(context)

        For Each order In orders
            Console.WriteLine(order.SalesOrderID)
        Next

    End Using
End Sub

Örnek 3

Aşağıdaki örnek, ürün listesi fiyatlarının ortalamasını değer olarak döndüren bir Decimal sorguyu derleyip çağırır:

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);
    }
}
Using context As New AdventureWorksEntities()
    Dim compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, Decimal)( _
            Function(ctx) ctx.Products.Average(Function(Product) Product.ListPrice))

    Dim averageProductPrice As Decimal = compQuery.Invoke(context)

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

Örnek 4

Aşağıdaki örnek, giriş parametresini kabul eden bir String sorguyu derleyip çağırır ve ardından e-posta adresi belirtilen dizeyle başlayan bir Contact sorgu döndürür:

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);
    }
}
Using context As New AdventureWorksEntities()
    Dim compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, String, Contact)( _
            Function(ctx, name) ctx.Contacts.First(Function(contact) contact.EmailAddress.StartsWith(name)))

    Dim contactName As String = "caroline"
    Dim foundContact As Contact = compQuery.Invoke(context, contactName)

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

Örnek 5

Aşağıdaki örnek, parametreleri kabul eden ve Decimal giriş parametrelerini kabul DateTime eden bir sorguyu derleyip çağırır ve sipariş tarihinin 8 Mart 2003'ten sonra olduğu ve toplam son tarihin 300,00 TL'den az olduğu bir sipariş dizisi döndürür:

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);
        }
    }
}
ReadOnly s_compQuery5 = _
   CompiledQuery.Compile(Of AdventureWorksEntities, DateTime, Decimal, IQueryable(Of SalesOrderHeader))( _
                Function(ctx, orderDate, totalDue) From product In ctx.SalesOrderHeaders _
                                                   Where product.OrderDate > orderDate _
                                                      And product.TotalDue < totalDue _
                                                   Order By product.OrderDate _
                                                   Select product)
Sub CompiledQuery5()

    Using context As New AdventureWorksEntities()

        Dim orderedAfterDate As DateTime = New DateTime(2003, 3, 8)
        Dim amountDue As Decimal = 300.0

        Dim orders As IQueryable(Of SalesOrderHeader) = _
            s_compQuery5.Invoke(context, orderedAfterDate, amountDue)

        For Each order In orders
            Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", _
                              order.SalesOrderID, order.OrderDate, order.TotalDue)
        Next

    End Using
End Sub

Örnek 6

Aşağıdaki örnek, giriş parametresini kabul eden bir DateTime sorguyu derleyip çağırır ve sipariş tarihinin 8 Mart 2004'ten sonra olduğu bir sipariş dizisi döndürür. Bu sorgu, sipariş bilgilerini anonim türlerin dizisi olarak döndürür. Anonim türler derleyici tarafından çıkarılır, bu nedenle 's Compile yönteminde CompiledQuerytür parametreleri belirtemezsiniz ve tür sorgunun kendisinde tanımlanır.

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);
    }
}
Using context As New AdventureWorksEntities()
    Dim compQuery = CompiledQuery.Compile( _
            Function(ctx As AdventureWorksEntities, orderDate As DateTime) _
                From order In ctx.SalesOrderHeaders _
                Where order.OrderDate > orderDate _
                Select New With {order.OrderDate, order.SalesOrderID, order.TotalDue})

    Dim orderedAfterDate As DateTime = New DateTime(2004, 3, 8)

    Dim orders = compQuery.Invoke(context, orderedAfterDate)

    For Each order In orders
        Console.WriteLine("ID: {0} Order date: {1} Total due: {2}", _
                          order.SalesOrderID, order.OrderDate, order.TotalDue)
    Next

End Using

Örnek 7

Aşağıdaki örnek, kullanıcı tanımlı yapı giriş parametresini kabul eden ve bir dizi sipariş döndüren bir sorguyu derleyip çağırır. Yapı başlangıç tarihi, bitiş tarihi ve toplam son tarih sorgu parametrelerini tanımlar ve sorgu, 3-8 Mart 2003 tarihleri arasında gönderilen siparişleri döndürür ve toplam vadesi 700,00 TL'den fazla olur.

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);
        }
    }
}
ReadOnly s_compQuery = CompiledQuery.Compile(Of AdventureWorksEntities, MyParams, IQueryable(Of SalesOrderHeader))( _
                Function(ctx, mySearchParams) _
                    From sale In ctx.SalesOrderHeaders _
                    Where sale.ShipDate > mySearchParams.startDate _
                       And sale.ShipDate < mySearchParams.endDate _
                       And sale.TotalDue > mySearchParams.totalDue _
                    Select sale)

Sub CompiledQuery7()

    Using context As New AdventureWorksEntities()

        Dim myParams As MyParams = New MyParams()
        myParams.startDate = New DateTime(2003, 3, 3)
        myParams.endDate = New DateTime(2003, 3, 8)
        myParams.totalDue = 700.0

        Dim sales = s_compQuery.Invoke(context, myParams)

        For Each sale In sales
            Console.WriteLine("ID: {0}", sale.SalesOrderID)
            Console.WriteLine("Ship date: {0}", sale.ShipDate)
            Console.WriteLine("Total due: {0}", sale.TotalDue)
        Next

    End Using
End Sub

Sorgu parametrelerini tanımlayan yapı:

struct MyParams
{
    public DateTime startDate;
    public DateTime endDate;
    public decimal totalDue;
}
Public Structure MyParams
    Public startDate As DateTime
    Public endDate As DateTime
    Public totalDue As Decimal
End Structure

Ayrıca bkz.