Ismert problémák és szempontok a LINQ-ban az entitások között

Ez a szakasz a LINQ entitások lekérdezéseivel kapcsolatos ismert problémákról nyújt tájékoztatást.

Nem gyorsítótárazható LINQ-lekérdezések

A 4.5-ös .NET-keretrendszer kezdve a LINQ to Entities lekérdezések automatikusan gyorsítótárazva lesznek. A LINQ azonban nem lesz automatikusan gyorsítótárazva az olyan entitásokra vonatkozó lekérdezésekre, amelyek az Enumerable.Contains operátort a memóriában lévő gyűjteményekre alkalmazzák. A memóriabeli gyűjtemények paraméterezése a lefordított LINQ-lekérdezésekben sem engedélyezett.

Elveszett rendelési adatok

Az oszlopok névtelen típusba való kivetítése miatt egyes lekérdezésekben elvesznek a rendezési adatok, amelyeket egy SQL Server 2005-adatbázison hajtanak végre, és a kompatibilitási szintje "80". Ez akkor fordul elő, ha a sorrend szerinti listában szereplő oszlopnév megegyezik a választóban szereplő oszlopnévvel, ahogyan az a következő példában látható:

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

Nem aláírt egész számok nem támogatottak

A LINQ–Entitások lekérdezésben nem aláírt egész számtípus megadása nem támogatott, mert az Entity Framework nem támogatja az aláíratlan egész számokat. Ha aláíratlan egész számot ad meg, ArgumentException a lekérdezési kifejezés fordítása során kivétel jelenik meg, ahogy az alábbi példában is látható. Ez a példa egy 48000 azonosítójú rendelést kér le.

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: {0}", 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

Típuskonvertálási hibák

A Visual Basicben, ha egy tulajdonság egy SQL Server-bittípusú oszlopra van leképezve, amelynek értéke 1 a CByte függvény használatával, SqlException "Aritmetikai túlcsordulási hiba" üzenet jelenik meg. Az alábbi példa lekérdezi az Product.MakeFlag AdventureWorks mintaadatbázis oszlopát, és kivételt eredményez a lekérdezés eredményeinek iteratedálásakor.

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

Nem skaláris változókra való hivatkozás nem támogatott

Nem skaláris változók, például entitások lekérdezésben való hivatkozása nem támogatott. Egy ilyen lekérdezés végrehajtásakor a rendszer kivételt NotSupportedException jelez a következő üzenettel: "Nem hozható létre állandó típusú EntityTypeérték. Ebben a kontextusban csak a primitív típusok (például int32, sztring és guid) támogatottak."

Feljegyzés

A skaláris változók gyűjteményére való hivatkozás támogatott.

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: ", 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

A beágyazott lekérdezések meghiúsulhatnak az SQL Server 2000 használatával

Az SQL Server 2000 esetén az entitások LINQ-lekérdezései meghiúsulhatnak, ha beágyazott Transact-SQL-lekérdezéseket hoznak létre, amelyek három vagy több szinttel mélyebbek.

Kivetítés névtelen típusra

Ha a kezdeti lekérdezési útvonalat úgy határozza meg, hogy a kapcsolódó objektumokat a metódus ObjectQuery<T> használatával Include adja meg, majd a LINQ használatával a visszaadott objektumokat névtelen típusra kivetítse, a belefoglalási metódusban megadott objektumok nem szerepelnek a lekérdezés eredményei között.

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

A kapcsolódó objektumok lekéréséhez ne kivetítse a visszaadott típusokat névtelen típusra.

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

Lásd még