Delen via


Bekende problemen en overwegingen in LINQ naar entiteiten

Deze sectie bevat informatie over bekende problemen met LINQ naar entiteiten-query's.

LINQ-query's die niet in de cache kunnen worden opgeslagen

Vanaf .NET Framework 4.5 worden LINQ-query's naar entiteiten automatisch in de cache opgeslagen. LINQ op entiteitenquery's die de operator toepassen op in-memory verzamelingen, worden echter niet automatisch in de Enumerable.Contains cache opgeslagen. Het parameteriseren van in-memory verzamelingen in gecompileerde LINQ-query's is ook niet toegestaan.

Bestelgegevens verloren

Als u kolommen projecteert in een anoniem type, gaan bestelgegevens verloren in sommige query's die worden uitgevoerd op een SQL Server 2005-database die is ingesteld op een compatibiliteitsniveau van '80'. Dit gebeurt wanneer een kolomnaam in de order-by-lijst overeenkomt met een kolomnaam in de selector, zoals wordt weergegeven in het volgende voorbeeld:

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

Niet-ondertekende gehele getallen worden niet ondersteund

Het opgeven van een niet-ondertekend geheel getal in een LINQ naar entiteiten-query wordt niet ondersteund omdat het Entity Framework geen niet-ondertekende gehele getallen ondersteunt. Als u een geheel getal zonder teken opgeeft, wordt er een ArgumentException uitzondering gegenereerd tijdens de vertaling van de query-expressie, zoals wordt weergegeven in het volgende voorbeeld. In dit voorbeeld wordt een query uitgevoerd voor een order met 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: {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

Typeconversiefouten

Wanneer in Visual Basic een eigenschap is toegewezen aan een kolom van het SQL Server-bittype met een waarde van 1 met behulp van de CByte functie, wordt er een SqlException foutbericht 'Rekenkundige overloopfout' gegenereerd. In het volgende voorbeeld wordt de Product.MakeFlag kolom in de AdventureWorks-voorbeelddatabase opgevraagd en er wordt een uitzondering gegenereerd wanneer de queryresultaten worden overschreven.

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

Verwijzingen naar niet-scalaire variabelen worden niet ondersteund

Het verwijzen naar een niet-scalaire variabelen, zoals een entiteit, in een query wordt niet ondersteund. Wanneer een dergelijke query wordt uitgevoerd, wordt er een NotSupportedException uitzondering gegenereerd met een bericht met de tekst 'Kan geen constante waarde van het type EntityTypemaken. In deze context worden alleen primitieve typen ('zoals Int32, String en Guid') ondersteund.

Notitie

Verwijzen naar een verzameling scalaire variabelen wordt ondersteund.

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

Geneste query's mislukken mogelijk met SQL Server 2000

Met SQL Server 2000 kunnen LINQ naar entiteiten-query's mislukken als ze geneste Transact-SQL-query's produceren die drie of meer niveaus diep zijn.

Projecteren naar een anoniem type

Als u het eerste querypad definieert om gerelateerde objecten op te nemen met behulp van de Include methode op de ObjectQuery<T> en vervolgens LINQ gebruikt om de geretourneerde objecten te projecteren op een anoniem type, worden de objecten die zijn opgegeven in de include-methode, niet opgenomen in de queryresultaten.

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

Als u gerelateerde objecten wilt ophalen, projecteert u geen geretourneerde typen naar een anoniem type.

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

Zie ook