다음을 통해 공유


LINQ to Entities의 알려진 문제 및 고려 사항

이 섹션에서는 LINQ to Entities 쿼리의 알려진 문제에 대한 정보를 제공합니다.

캐시할 수 없는 LINQ 쿼리

.NET Framework 4.5부터 LINQ to Entities 쿼리는 자동으로 캐시됩니다. 그러나 메모리 내 컬렉션에 Enumerable.Contains 연산자를 적용하는 LINQ to Entities 쿼리는 자동으로 캐시되지 않습니다. 또한 컴파일된 LINQ 쿼리에서 메모리 내 컬렉션을 매개 변수화할 수 없습니다.

주문 정보 손실

열을 익명 형식으로 프로젝션하면 호환성 수준 "80"으로 설정된 SQL Server 2005 데이터베이스에 대해 실행되는 일부 쿼리에서 순서 지정 정보가 손실됩니다. 이는 다음 예제와 같이 순서별 목록의 열 이름이 선택기에서 열 이름과 일치할 때 발생합니다.

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

부호 없는 정수가 지원되지 않음

Entity Framework에서 부호 없는 정수를 지원하지 않으므로 LINQ to Entities 쿼리에서 부호 없는 정수 형식 지정은 지원되지 않습니다. 부호 없는 정수를 지정하면 다음 예제와 같이 쿼리 식 변환 중에 ArgumentException 예외가 throw됩니다. 이 예제에서는 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

형식 변환 오류

Visual Basic에서 속성이 CByte 함수를 사용하여 값이 1인 SQL Server 비트 형식의 열에 매핑될 때 "산술 오버플로 오류" 메시지와 함께 SqlException 예외가 발생합니다. 다음 예제에서는 AdventureWorks 샘플 데이터베이스의 Product.MakeFlag 열을 쿼리하고 쿼리 결과가 반복될 때 예외가 throw됩니다.

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

지원되지 않는 비 스칼라 변수 참조

쿼리에서 엔터티와 같은 스칼라가 아닌 변수를 참조하는 것은 지원되지 않습니다. 해당 쿼리가 실행될 때, “NotSupportedException형식의 상수 값을 만들 수 없습니다”라는 메시지와 함께 EntityType 예외가 발생합니다. 이 컨텍스트에서는 기본 형식(예: Int32, String 및 Guid')만 지원됩니다."

비고

스칼라 변수 컬렉션을 참조하는 것이 지원됩니다.

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

SQL Server 2000에서 중첩 쿼리가 실패할 수 있음

SQL Server 2000에서는 LINQ to Entities 쿼리가 3개 이상의 수준 깊이의 중첩된 Transact-SQL 쿼리를 생성하는 경우 실패할 수 있습니다.

익명 형식으로의 투영

Include ObjectQuery<T> 메서드를 사용하여 관련 개체를 포함하도록 초기 쿼리 경로를 정의한 다음 LINQ를 사용하여 반환된 개체를 익명 형식으로 프로젝션하는 경우 include 메서드에 지정된 개체는 쿼리 결과에 포함되지 않습니다.

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

관련 개체를 얻으려면 반환된 형식을 익명 형식으로 프로젝션하지 마세요.

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

참고하십시오