Bagikan melalui


Masalah dan Pertimbangan umum dalam LINQ ke Entitas

Bagian ini menyediakan informasi tentang masalah yang diketahui dengan LINQ untuk kueri Entitas.

Kueri LINQ Yang tidak dapat Di-cache

Dimulai dengan .NET Framework 4.5, kueri LINQ ke Entitas secara otomatis di-cache. Namun, kueri LINQ ke Entitas yang menerapkan Enumerable.Contains operator ke dalam koleksi memori tidak secara otomatis di-cache. Parameterisasi koleksi yang ada dalam memori pada kueri LINQ yang dikompilasi juga tidak diperbolehkan.

Informasi Pemesanan Hilang

Memproyeksikan kolom ke dalam jenis anonim akan menyebabkan informasi pengurutan hilang dalam beberapa kueri yang dijalankan terhadap database SQL Server 2005 yang diatur ke tingkat kompatibilitas "80". Ini terjadi ketika nama kolom dalam daftar pengurutan cocok dengan nama kolom di penyeleksi, seperti yang ditunjukkan dalam contoh berikut:

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    // Ordering information is lost when executed against a SQL Server 2005
    // database running with a compatibility level of "80".
    var results = context.Contacts.SelectMany(c => c.SalesOrderHeaders)
        .OrderBy(c => c.SalesOrderDetails.Count)
        .Select(c => new { c.SalesOrderDetails.Count });

    foreach (var result in results)
        Console.WriteLine(result.Count);
}
Using context As New AdventureWorksEntities()
    ' Ordering information is lost when executed against a SQL Server 2005
    ' database running with a compatibility level of "80".
    Dim results = context.Contacts.SelectMany(Function(c) c.SalesOrderHeaders) _
        .OrderBy(Function(c) c.SalesOrderDetails.Count) _
        .Select(Function(c) New With {c.SalesOrderDetails.Count})

    For Each result In results
        Console.WriteLine(result.Count)
    Next
End Using

Dukungan untuk Bilangan Bulat Tanpa Tanda Tidak Tersedia

Menentukan jenis bilangan bulat yang tidak ditandatangani dalam kueri LINQ ke Entitas tidak didukung karena Kerangka Kerja Entitas tidak mendukung bilangan bulat yang tidak ditandatangani. Jika Anda menentukan integer tanpa tanda, pengecualian ArgumentException akan terjadi selama terjemahan ekspresi kueri, seperti yang diperlihatkan dalam contoh berikut. Contoh ini mencari pesanan dengan ID 48000.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    uint s = UInt32.Parse("48000");

    IQueryable<SalesOrderDetail> query = from sale in context.SalesOrderDetails
                                         where sale.SalesOrderID == s
                                         select sale;

    // NotSupportedException exception is thrown here.
    try
    {
        foreach (SalesOrderDetail order in query)
            Console.WriteLine("SalesOrderID: " + order.SalesOrderID);
    }
    catch (NotSupportedException ex)
    {
        Console.WriteLine($"Exception: {ex.Message}");
    }
}
Using context As New AdventureWorksEntities()
    Dim saleId As UInteger = UInt32.Parse("48000")

    Dim query = _
        From sale In context.SalesOrderDetails _
        Where sale.SalesOrderID = saleId _
        Select sale

    Try
        ' NotSupportedException exception is thrown here.
        For Each order As SalesOrderDetail In query
            Console.WriteLine("SalesOrderID: " & order.SalesOrderID)
        Next
    Catch ex As NotSupportedException
        Console.WriteLine("Exception: " + ex.Message)
    End Try
End Using

Kesalahan Konversi Jenis

Di Visual Basic, ketika properti dipetakan ke kolom jenis bit SQL Server dengan nilai 1 menggunakan CByte fungsi , dilemparkan SqlException dengan pesan "Kesalahan luapan aritmatika". Contoh berikut melakukan kueri pada kolom Product.MakeFlag dalam database sampel AdventureWorks dan pengecualian terjadi ketika iterasi hasil kueri dilakukan.

Using context As New AdventureWorksEntities()
    Dim productsList = _
        From product In context.Products _
        Select CByte(product.MakeFlag)

    ' Throws an SqlException exception with a "Arithmetic overflow error 
    ' for data type tinyint" message when a value of 1 is iterated over.
    For Each makeFlag In productsList
        Console.WriteLine(makeFlag)
    Next
End Using

Mereferensikan Variabel Non-Skalar Tidak Didukung

Mereferensikan variabel non-skalar, seperti entitas, dalam kueri tidak didukung. Ketika kueri seperti itu dijalankan, NotSupportedException pengecualian dilemparkan dengan pesan yang menyatakan "Tidak dapat membuat nilai konstan jenis EntityType. Hanya jenis primitif ('seperti Int32, String, dan Guid') yang didukung dalam konteks ini."

Nota

Mereferensikan kumpulan variabel skalar didukung.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    Contact contact = context.Contacts.FirstOrDefault();

    // Referencing a non-scalar closure in a query will
    // throw an exception when the query is executed.
    IQueryable<string> contacts = from c in context.Contacts
        where c == contact
        select c.LastName;

    try
    {
        foreach (string name in contacts)
        {
            Console.WriteLine($"Name: ");
        }
    }
    catch (NotSupportedException ex)
    {
        Console.WriteLine(ex.Message);
    }
}
Using context As New AdventureWorksEntities()

    Dim contact As Contact = context.Contacts.FirstOrDefault()

    ' Referencing a non-scalar closure in a query will
    ' throw an exception when the query is executed.
    Dim contacts = From c In context.Contacts _
                   Where c.Equals(contact) _
                   Select c.LastName

    Try
        For Each name As String In contacts
            Console.WriteLine("Name: ", name)
        Next

    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try

End Using

Kueri Bersarang Mungkin Gagal pada SQL Server 2000

Dengan SQL Server 2000, kueri LINQ ke Entitas mungkin gagal jika menghasilkan kueri Transact-SQL berlapis yang memiliki tiga tingkat atau lebih dalam.

Memproyeksikan ke Tipe Anonim

Jika Anda menentukan jalur kueri awal untuk menyertakan objek terkait dengan menggunakan Include metode pada ObjectQuery<T> lalu menggunakan LINQ untuk memproyeksikan objek yang dikembalikan ke jenis anonim, objek yang ditentukan dalam metode sertakan tidak disertakan dalam hasil kueri.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    var resultWithoutRelatedObjects =
        context.Contacts.Include("SalesOrderHeaders").Select(c => new { c }).FirstOrDefault();
    if (resultWithoutRelatedObjects.c.SalesOrderHeaders.Count == 0)
    {
        Console.WriteLine("No orders are included.");
    }
}
Using context As New AdventureWorksEntities()
    Dim resultWithoutRelatedObjects = context.Contacts. _
        Include("SalesOrderHeaders"). _
        Select(Function(c) New With {c}).FirstOrDefault()
    If resultWithoutRelatedObjects.c.SalesOrderHeaders.Count = 0 Then
        Console.WriteLine("No orders are included.")
    End If
End Using

Untuk mendapatkan objek terkait, jangan proyeksikan jenis yang dikembalikan ke jenis anonim.

using (AdventureWorksEntities context = new AdventureWorksEntities())
{
    var resultWithRelatedObjects =
        context.Contacts.Include("SalesOrderHeaders").Select(c => c).FirstOrDefault();
    if (resultWithRelatedObjects.SalesOrderHeaders.Count != 0)
    {
        Console.WriteLine("Orders are included.");
    }
}
Using context As New AdventureWorksEntities()
    Dim resultWithRelatedObjects = context.Contacts. _
        Include("SalesOrderHeaders"). _
        Select(Function(c) c).FirstOrDefault()
    If resultWithRelatedObjects.SalesOrderHeaders.Count <> 0 Then
        Console.WriteLine("Orders are included.")
    End If
End Using

Lihat juga