다음을 통해 공유


EF9(EF Core 9)의 호환성이 손상되는 변경

이 페이지는 EF Core 8에서 EF Core 9로 업데이트되는 기존 애플리케이션의 호환성이 손상될 수 있는 API 및 동작 변경을 기록합니다. 이전 버전의 EF Core에서 업데이트하는 경우 이전의 호환성이 손상되는 변경을 검토합니다.

대상 프레임워크

EF Core 9는 .NET 8을 대상으로 합니다. 즉, .NET 8을 대상으로 하는 기존 애플리케이션은 계속 그렇게 할 수 있습니다. 이전 .NET, .NET Core 및 .NET Framework 버전을 대상으로 하는 애플리케이션은 EF Core 9를 사용하려면 .NET 8 또는 .NET 9를 대상으로 해야 합니다.

요약

참고 항목

Azure Cosmos DB를 사용하는 경우 Azure Cosmos DB 호환성이 손상되는 변경에 대한 아래의 별도 섹션을 참조하세요.

주요 변경 내용 영향
보류 중인 모델 변경 내용이 있는 경우 마이그레이션을 적용할 때 예외가 발생합니다 높음
명시적 트랜잭션 마이그레이션을 적용할 때 예외가 throw됩니다. 높음
EF.Functions.Unhex()가 이제 byte[]?를 반환합니다. 낮음
SqlFunctionExpression의 Null 허용 여부 인수의 arity 유효성이 검사됨 낮음
ToString() 메서드는 이제 인스턴스에 대해 빈 문자열을 null 반환합니다. 낮음
공유 프레임워크 종속성이 9.0.x로 업데이트되었습니다. 낮음

높은 영향을 주는 변경 내용

보류 중인 모델 변경 내용이 있는 경우 마이그레이션을 적용할 때 예외가 발생합니다.

추적 문제 #33732

이전 동작

모델에 마지막 마이그레이션과 비교하여 보류 중인 변경 내용이 있는 경우 Migrate 호출될 때 나머지 마이그레이션에는 적용되지 않습니다.

새 동작

EF Core 9.0부터 모델에 마지막 마이그레이션과 비교하여 보류 중인 변경 내용이 있을 경우 dotnet ef database update, Migrate 또는 MigrateAsync가 호출될 때 예외가 발생합니다.

컨텍스트 'DbContext'의 모델에 보류 중인 변경 내용이 있습니다. 데이터베이스를 업데이트하기 전에 새 마이그레이션을 추가합니다. 이벤트 ID 'RelationalEventId.PendingModelChangesWarning'을 'DbContext.OnConfiguring' 또는 'AddDbContext'의 'ConfigureWarnings' 메서드에 전달하여 이 예외를 표시하지 않거나 기록할 수 있습니다.

이유

모델을 변경한 후 새 마이그레이션을 추가하는 것을 잊어버리는 것은 경우에 따라 진단하기 어려울 수 있는 일반적인 실수입니다. 새 예외는 마이그레이션이 적용된 후 앱의 모델이 데이터베이스와 일치하도록 합니다.

해결 방법

이 예외가 발생할 수 있는 몇 가지 일반적인 상황이 있습니다.

  • 마이그레이션은 전혀 없습니다. 이는 데이터베이스가 다른 방법을 통해 업데이트되는 경우에 일반적입니다.
    • 완화: 데이터베이스 스키마를 관리하기 위해 마이그레이션을 사용하지 않으려는 경우 Migrate 또는 MigrateAsync 호출을 제거합니다. 그렇지 않으면 마이그레이션을 추가합니다.
  • 하나 이상의 마이그레이션이 있지만 모델 스냅샷이 없습니다. 이는 수동으로 만든 마이그레이션에 일반적입니다.
    • 완화: EF 도구를 사용하여 새 마이그레이션을 추가하면 모델 스냅샷이 업데이트됩니다.
  • 개발자가 모델을 수정하지 않았지만, 비결정적인 방식으로 빌드되어 EF가 이를 수정된 것으로 감지합니다. 이는 new DateTime()에 제공된 개체에서 DateTime.Now, DateTime.UtcNow, Guid.NewGuid()또는 HasData()가 사용될 때 일반적입니다.
    • 완화: 새 마이그레이션을 추가하고, 해당 내용을 검사하여 원인을 찾고, 동적 데이터를 모델의 정적 하드 코드된 값으로 바꿉니다. 모델이 수정된 후 마이그레이션을 다시 만들어야 합니다. 동적 데이터를 시드에 사용해야 하는 경우 대신 새 시드 패턴 사용하는 것이 좋습니다.
  • 마지막 마이그레이션은 마이그레이션을 적용하는 데 사용된 것과 다른 공급자에 대해 만들어졌습니다.
    • 완화: 지원되지 않는 시나리오입니다. 아래 코드 조각을 사용하여 경고를 무시할 수 있지만, 이 시나리오는 향후 EF Core 릴리스에서 더 이상 작동하지 않게 될 가능성이 높습니다. 권장되는 솔루션은 각 공급자에 대해 별도의 마이그레이션 집합을 생성하는 입니다.
  • 마이그레이션은 일부 EF 서비스를 대체하여 동적으로 생성되거나 선택됩니다.
    • 완화: 이 경우 경고는 오탐이므로 억제해야 합니다.

      options.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))

시나리오가 위의 사례에 속하지 않고 새 마이그레이션을 추가할 때마다 동일한 마이그레이션이 생성되거나 빈 마이그레이션이 만들어지며 예외가 계속 발생하는 경우, 작은 재현 프로젝트를 생성하여 새 문제를 등록하고이 프로젝트를 EF 팀과 공유하십시오 .

명시적 트랜잭션에서 마이그레이션을 적용할 때 예외가 발생됩니다.

추적 문제 #17578

이전 동작

복원력 있는 마이그레이션을 적용하기 위해 일반적으로 다음과 같은 패턴이 사용되었습니다.

await dbContext.Database.CreateExecutionStrategy().ExecuteAsync(async () =>
{
    await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
    await dbContext.Database.MigrateAsync(cancellationToken);
    await transaction.CommitAsync(cancellationToken);
});

새 동작

EF Core 9.0부터 MigrateMigrateAsync 호출은 트랜잭션을 시작하고, ExecutionStrategy를 사용하여 명령을 실행합니다. 만약 앱에서 이 패턴을 사용할 경우, 예외가 발생합니다.

'Microsoft.EntityFrameworkCore.Migrations.MigrationsUserTransactionWarning' 경고에 대한 오류가 발생했습니다. 마이그레이션을 적용하기 전에 트랜잭션이 시작되었습니다. 이렇게 하면 데이터베이스 잠금을 획득할 수 없으므로 데이터베이스가 동시 마이그레이션 애플리케이션으로부터 보호되지 않습니다. 트랜잭션 및 실행 전략은 필요에 따라 EF에서 이미 관리됩니다. 외부 트랜잭션을 제거합니다. 이벤트 ID 'RelationalEventId.MigrationsUserTransactionWarning'을 'DbContext.OnConfiguring' 또는 'AddDbContext'의 'ConfigureWarnings' 메서드에 전달하여 이 예외를 표시하지 않거나 기록할 수 있습니다.

이유

명시적 트랜잭션을 사용하면 데이터베이스 잠금을 획득할 수 없으므로 데이터베이스가 동시 마이그레이션 애플리케이션으로부터 보호되지 않으므로 트랜잭션을 내부적으로 관리하는 방법에 대한 EF도 제한됩니다.

해결 방법

트랜잭션 내에 데이터베이스 호출이 하나만 있는 경우 외부 트랜잭션을 제거하고 ExecutionStrategy:

await dbContext.Database.MigrateAsync(cancellationToken);

그렇지 않은 경우 시나리오에 명시적 트랜잭션이 필요하고 동시 마이그레이션 애플리케이션을 방지하기 위한 다른 메커니즘이 있는 경우 경고를 무시합니다.

options.ConfigureWarnings(w => w.Ignore(RelationalEventId.MigrationsUserTransactionWarning))

낮은 영향을 주는 변경 내용

EF.Functions.Unhex()가 이제 byte[]?를 반환합니다.

추적 이슈 #33864

이전 동작

EF.Functions.Unhex() 함수는 이전에 byte[]를 반환하도록 주석이 추가되었습니다.

새 동작

EF Core 9.0부터 Unhex()는 이제 byte[]?을(를) 반환하도록 주석이 추가됩니다

이유

Unhex()는 잘못된 입력에 대해 NULL을 반환하는 SQLite unhex 함수로 변환됩니다. 결과적으로 Unhex()는 주석을 위반하여 이러한 경우에 대해 null을 반환했습니다.

해결 방법

Unhex()에 전달된 텍스트 콘텐츠가 유효한 16진수 문자열을 나타내는 것이 확실하다면, 호출이 절대로 null을 반환하지 않는다는 어설션으로 null 허용 연산자를 추가하면 됩니다

var binaryData = await context.Blogs.Select(b => EF.Functions.Unhex(b.HexString)!).ToListAsync();

그렇지 않으면 Unhex()의 반환 값에 null에 대한 런타임 검사를 추가합니다.

SqlFunctionExpression의 Null 허용 여부 인수의 arity 유효성이 검사됨

추적 이슈 #33852

이전 동작

이전에는 다른 수의 인수와 null 허용 여부 전파 인수를 사용하여 SqlFunctionExpression을(를) 만들 수 있었습니다.

새 동작

EF Core 9.0부터 EF는 이제 인수 수와 null 허용 여부 전파 인수가 일치하지 않으면 throw됩니다.

이유

일치하는 인수 수와 Null 허용 여부 전파 인수가 없으면 예기치 않은 동작이 발생할 수 있습니다.

해결 방법

argumentsPropagateNullabilityarguments와(과) 같은 수의 요소가 있는지 확인합니다. 의심스러운 경우 null 허용 여부 인수에 false을(를) 사용합니다.

ToString() 메서드는 이제 인스턴스에 대해 빈 문자열을 null 반환합니다.

추적 문제 #33941

이전 동작

이전에 EF는 인수 값이 있을 때 메서드에 ToString() 대해 일관되지 않은 결과를 반환했습니다 null. 예를 들어 값이 ToString() 반환된 속성에서 값이 반환bool?nullnull 속성 bool? 이 아닌 식의 경우입니다. nullTrue 다른 데이터 형식(예: 값 열거형이 빈 문자열을 ToString() 반환하는 경우null)에도 동작이 일치하지 않았습니다.

새 동작

EF Core 9.0부터 메서드는 ToString() 이제 인수 값이 null있을 때 모든 경우에 빈 문자열을 일관되게 반환합니다.

이유

이전 동작은 서로 다른 데이터 형식 및 상황에서 일관성이 없을 뿐만 아니라 C# 동작일치하지 않았습니다.

해결 방법

이전 동작으로 되돌리려면 그에 따라 쿼리를 다시 작성합니다.

var newBehavior = context.Entity.Select(x => x.NullableBool.ToString());
var oldBehavior = context.Entity.Select(x => x.NullableBool == null ? null : x.NullableBool.ToString());

공유 프레임워크 종속성이 9.0.x로 업데이트되었습니다.

이전 동작

SDK를 사용하고 Microsoft.NET.Sdk.Web net8.0을 대상으로 하는 앱은 공유 프레임워크와 System.Text.Json 같은 Microsoft.Extensions.Caching.MemoryMicrosoft.Extensions.Configuration.AbstractionsMicrosoft.Extensions.LoggingMicrosoft.Extensions.DependencyModel 패키지를 확인하므로 이러한 어셈블리는 일반적으로 앱과 함께 배포되지 않습니다.

새 동작

EF Core 9.0은 여전히 net8.0을 지원하지만 이제는 9.0.x 버전의 System.Text.Json, Microsoft.Extensions.Caching.MemoryMicrosoft.Extensions.Configuration.AbstractionsMicrosoft.Extensions.Logging및 .Microsoft.Extensions.DependencyModel net8.0을 대상으로 하는 앱은 공유 프레임워크를 활용하여 이러한 어셈블리를 배포하지 않도록 할 수 없습니다.

이유

일치하는 종속성 버전에는 최신 보안 수정 사항이 포함되어 있으며 이를 사용하면 EF Core에 대한 서비스 모델이 간소화됩니다.

해결 방법

이전 동작을 가져오기 위해 앱을 대상 net9.0으로 변경합니다.

Azure Cosmos DB 호환성이 손상되는 변경

9.0에서 Azure Cosmos DB 공급자를 개선하기 위한 광범위한 작업이 진행되었습니다. 변경 내용에는 많은 영향을 미치는 호환성이 손상되는 변경이 포함됩니다. 기존 애플리케이션을 업그레이드하는 경우 다음을 주의 깊게 읽어 보세요.

주요 변경 내용 영향
$type 대신 Discriminator으로 지정됨 높음
id 속성은 기본적으로 판별자를 더 이상 포함하지 않음 높음
JSON id 속성이 키에 매핑된다. 높음
Azure Cosmos DB 공급자를 통한 동기화 I/O는 더 이상 지원되지 않음 중간
SQL 쿼리는 이제 JSON 값을 직접 프로젝트해야 함 중간
이제 쿼리 결과에서 정의되지 않은 결과가 자동으로 필터링됨 중간
잘못 변환된 쿼리는 더 이상 변환되지 않음 중간
HasIndex가 이제 무시되는 대신 throw됨 낮음
IncludeRootDiscriminatorInJsonId가 9.0.0-rc.2 이후 HasRootDiscriminatorInJsonId로 이름이 변경됨 낮음

높은 영향을 주는 변경 내용

이제 판별자 속성의 이름은 $type 대신 Discriminator으로 지정됨

추적 문제 #34269

이전 동작

EF는 JSON 문서에 판별자 속성을 자동으로 추가하여 문서가 나타내는 엔터티 형식을 식별합니다. 이전 버전의 EF에서 이 JSON 속성은 기본적으로 이름이 Discriminator로 지정되었습니다.

새 동작

EF Core 9.0부터 판별자 속성은 이제 기본적으로 $type이라고 합니다. 이전 버전의 EF에서 Azure Cosmos DB에 기존 문서가 있는 경우 이전 Discriminator 명명을 사용하고 EF 9.0으로 업그레이드한 후 해당 문서에 대한 쿼리가 실패합니다.

이유

새로운 JSON 사례는 문서의 형식을 식별해야 하는 시나리오에서 $type 속성을 사용합니다. 예를 들어. NET의 System.Text.Json은 $type을 기본 판별자 속성 이름(docs)으로 사용하여 다형성도 지원합니다. 나머지 에코시스템에 맞게 외부 도구와 쉽게 상호 운용할 수 있도록 기본값이 변경되었습니다.

해결 방법

가장 쉬운 완화 방법은 이전과 마찬가지로 판별자 속성의 이름을 Discriminator로 구성하기만 하면 됩니다.

modelBuilder.Entity<Session>().HasDiscriminator<string>("Discriminator");

모든 최상위 엔터티 형식에 대해 이 작업을 수행하면 EF가 이전처럼 동작하게 됩니다.

이 시점에서 원하는 경우 새 $type 이름을 사용하도록 모든 문서를 업데이트할 수도 있습니다.

이제 id 속성에는 기본적으로 EF 키 속성만 포함됨

추적 문제 #34179

이전 동작

이전에 EF는 엔터티 형식의 판별자 값을 문서의 id 속성에 삽입했습니다. 예를 들어 8을 포함하는 Blog 속성이 있는 Id 엔터티 형식을 저장한 경우 JSON id 속성에는 Blog|8이 포함됩니다.

새 동작

EF Core 9.0부터 JSON id 속성은 더 이상 판별자 값을 포함하지 않으며 키 속성의 값만 포함합니다. 위의 예제에서 JSON id 속성은 단순히 8입니다. 이전 버전의 EF에서 Azure Cosmos DB에 기존 문서가 있는 경우 JSON id 속성에 판별자 값이 있으며 EF 9.0으로 업그레이드한 후 해당 문서에 대한 쿼리가 실패합니다.

이유

JSON id 속성은 고유해야 하므로 이전에 동일한 키 값을 가진 다른 엔터티가 존재할 수 있도록 판별자가 추가되었습니다. 예를 들어 동일한 컨테이너 및 Blog 파티션 내에 값 8이 포함된 속성과 Post a를 둘 다 Id 사용할 수 있습니다. 이는 각 엔터티 형식이 자체 테이블에 매핑되므로 고유한 키 공간이 있는 관계형 데이터베이스 데이터 모델링 패턴에 더 잘 맞습니다.

EF 9.0은 일반적으로 관계형 데이터베이스에서 들어오는 사용자의 기대에 부합하는 대신 일반적인 Azure Cosmos DB NoSQL 사례 및 기대에 맞게 매핑을 변경했습니다. 또한 id 속성에 판별자 값이 있으면 외부 도구 및 시스템이 EF 생성 JSON 문서와 상호 작용하는 것이 더 어려워졌습니다. 이러한 외부 시스템은 일반적으로 .NET 형식에서 파생된 EF 판별자 값을 인식하지 못합니다.

해결 방법

가장 쉬운 완화 방법은 이전과 같이 JSON id 속성에 판별자를 포함하도록 EF를 구성하는 것입니다. 이 목적을 위해 새 구성 옵션이 도입되었습니다.

modelBuilder.Entity<Session>().HasDiscriminatorInJsonId();

모든 최상위 엔터티 형식에 대해 이 작업을 수행하면 EF가 이전처럼 동작하게 됩니다.

이 시점에서 원하는 경우 모든 문서를 업데이트하여 JSON id 속성을 다시 작성할 수도 있습니다. 이는 다른 형식의 엔터티가 동일한 컨테이너 내에서 동일한 ID 값을 공유하지 않는 경우에만 가능합니다.

JSON id 속성이 키에 매핑됩니다.

추적 문제 #34179

이전 동작

이전에 EF는 속성 중 하나가 id에 명시적으로 매핑되지 않은 경우에 JSON id 속성에 매핑된 섀도 속성을 생성했습니다.

새 동작

EF Core 9부터 키 속성은 가능한 경우 규칙에 따라 JSON id 속성에 매핑됩니다. 즉, 키 속성이 더 이상 동일한 값을 가진 다른 이름으로 문서에 유지되지 않으므로 문서를 사용하고 있는 이 속성에 의존하는 비 EF 코드가 더 이상 제대로 작동하지 않습니다.

이유

EF 9.0은 일반적으로 일반적인 Azure Cosmos DB NoSQL 사례 및 기대에 맞게 매핑을 변경했습니다. 또한 키 값을 문서에 두 번 저장하는 것은 일반적이지 않습니다.

해결 방법

EF Core 8 동작을 유지하려는 경우 가장 쉬운 완화 방법은 이 목적을 위해 도입된 새 구성 옵션을 사용하는 것입니다.

modelBuilder.Entity<Session>().HasShadowId();

모든 최상위 엔터티 형식에 대해 이 작업을 수행하면 EF가 이전처럼 동작하게 됩니다. 또는 한 번의 호출로 모델의 모든 엔터티 형식에 적용할 수 있습니다.

modelBuilder.HasShadowIds();

중간 영향을 주는 변경 내용

Azure Cosmos DB 공급자를 통한 I/O 동기화는 더 이상 지원되지 않음

추적 이슈 #32563

이전 동작

이전에는 Azure Cosmos DB SDK에 대해 비동기 호출을 실행할 때 ToList 또는 SaveChanges와 같은 동기 메서드를 호출하면 EF Core가 .GetAwaiter().GetResult()를 사용하여 동기적으로 차단되었습니다. 이로 인해 교착 상태가 발생할 수 있습니다.

새 동작

EF Core 9.0부터 EF는 이제 동기 I/O를 사용하려고 시도할 때 기본적으로 오류를 throw합니다. 예외 메시지는 "Azure Cosmos DB는 동기 I/O를 지원하지 않습니다. Entity Framework Core를 사용하여 Azure Cosmos DB에 액세스하는 경우 비동기 메서드만 사용하고 올바르게 대기해야 합니다. 자세한 내용은 https://aka.ms/ef-cosmos-nosync를 참조하세요."

이유

비동기 메서드에 대한 동기 차단으로 인해 교착 상태가 발생할 수 있으며 Azure Cosmos DB SDK는 비동기 메서드만 지원합니다.

해결 방법

EF Core 9.0에서는 다음을 사용하여 오류를 표시하지 않을 수 있습니다.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.ConfigureWarnings(w => w.Ignore(CosmosEventId.SyncNotSupported));
}

즉, Azure Cosmos DB SDK에서는 지원되지 않으므로 애플리케이션은 Azure Cosmos DB와의 동기화 API 사용을 중지해야 합니다. 예외를 표시하지 않는 기능은 EF Core의 향후 릴리스에서 제거될 예정이며, 이후에는 유일한 옵션은 비동기 API를 사용하는 것입니다.

SQL 쿼리는 이제 JSON 값을 직접 프로젝트해야 함

추적 문제 #25527

이전 동작

이전에는 EF에서 다음과 같은 쿼리를 생성했습니다.

SELECT c["City"] FROM root c

이러한 쿼리로 인해 Azure Cosmos DB는 다음과 같이 각 결과를 JSON 개체로 래핑합니다.

[
    {
        "City": "Berlin"
    },
    {
        "City": "México D.F."
    }
]
새 동작

EF Core 9.0부터 EF는 이제 다음과 같이 쿼리에 VALUE 한정자를 추가합니다.

SELECT VALUE c["City"] FROM root c

이러한 쿼리로 인해 Azure Cosmos DB는 래핑되지 않고 값을 직접 반환합니다.

[
    "Berlin",
    "México D.F."
]

애플리케이션에서 SQL 쿼리를 사용하는 경우 이러한 쿼리는 VALUE 한정자를 포함하지 않으므로 EF 9.0으로 업그레이드한 후 해당 쿼리가 손상될 가능성이 높습니다.

이유

각 결과를 추가 JSON 개체로 래핑하면 일부 시나리오에서 성능이 저하되고 JSON 결과 페이로드가 부풀어 오르며 Azure Cosmos DB를 사용하는 자연스러운 방법이 아닙니다.

해결 방법

완화하려면 위와 같이 SQL 쿼리의 프로젝션에 VALUE 한정자를 추가하기만 하면 됩니다.

이제 쿼리 결과에서 정의되지 않은 결과가 자동으로 필터링됨

추적 문제 #25527

이전 동작

이전에는 EF에서 다음과 같은 쿼리를 생성했습니다.

SELECT c["City"] FROM root c

이러한 쿼리로 인해 Azure Cosmos DB는 다음과 같이 각 결과를 JSON 개체로 래핑합니다.

[
    {
        "City": "Berlin"
    },
    {
        "City": "México D.F."
    }
]

결과가 정의되지 않은 경우(예: City 속성이 문서에 없는 경우) 빈 문서가 반환되고 EF가 해당 결과에 대해 null을 반환합니다.

새 동작

EF Core 9.0부터 EF는 이제 다음과 같이 쿼리에 VALUE 한정자를 추가합니다.

SELECT VALUE c["City"] FROM root c

이러한 쿼리로 인해 Azure Cosmos DB는 래핑되지 않고 값을 직접 반환합니다.

[
    "Berlin",
    "México D.F."
]

Azure Cosmos DB 동작은 결과에서 값을 자동으로 필터링 undefined 하는 것입니다. 즉, 속성 중 City 하나가 문서에 없는 경우 쿼리는 두 개의 결과가 아닌 하나의 결과만 반환합니다 null.

이유

각 결과를 추가 JSON 개체로 래핑하면 일부 시나리오에서 성능이 저하되고 JSON 결과 페이로드가 부풀어 오르며 Azure Cosmos DB를 사용하는 자연스러운 방법이 아닙니다.

해결 방법

애플리케이션에서 정의되지 않은 결과에 대해 null 값을 가져오는 것이 중요한 경우, 새 undefined 연산자를 사용하여 null 값을 EF.Functions.Coalesce로 병합합니다.

var users = await context.Customer
    .Select(c => EF.Functions.CoalesceUndefined(c.City, null))
    .ToListAsync();

잘못 변환된 쿼리는 더 이상 변환되지 않음

추적 문제 #34123

이전 동작

이전에는 EF에서 다음과 같은 쿼리를 변환했습니다.

var sessions = await context.Sessions
    .Take(5)
    .Where(s => s.Name.StartsWith("f"))
    .ToListAsync();

그러나 이 쿼리에 대한 SQL 변환이 잘못되었습니다.

SELECT c
FROM root c
WHERE ((c["Discriminator"] = "Session") AND STARTSWITH(c["Name"], "f"))
OFFSET 0 LIMIT @__p_0

SQL에서 WHERE 절은 OFFSET 절보다 LIMIT 평가되지만, 위의 LINQ 쿼리에서는 Take 연산자 앞에 Where 연산자가 나타납니다. 따라서 이러한 쿼리는 잘못된 결과를 반환할 수 있습니다.

새 동작

EF Core 9.0부터 이러한 쿼리는 더 이상 변환되지 않으며 예외가 throw됩니다.

이유

잘못된 변환으로 인해 자동 데이터 손상이 발생할 수 있으므로 애플리케이션에서 발견하기 어려운 버그가 발생할 수 있습니다. EF는 항상 데이터 손상을 유발하는 대신 선행을 throw하여 페일 패스트(Fail-fast)를 선호합니다.

해결 방법

이전 동작에 만족하고 동일한 SQL을 실행하려는 경우 LINQ 연산자의 순서를 바꾸면 됩니다.

var sessions = await context.Sessions
    .Where(s => s.Name.StartsWith("f"))
    .Take(5)
    .ToListAsync();

아쉽게도 Azure Cosmos DB는 현재 원래 LINQ 쿼리의 적절한 변환에 필요한 SQL 하위 쿼리의 절 및 OFFSET 절을 지원하지 LIMIT 않습니다.

낮은 영향을 주는 변경 내용

HasIndex가 이제 무시되는 대신 throw됨

추적 문제 #34023

이전 동작

이전에는 EF Cosmos DB 공급자가 HasIndex에 대한 호출을 무시했습니다.

새 동작

HasIndex가 지정된 경우 이제 공급자가 throw됩니다.

이유

Azure Cosmos DB에서 모든 속성은 기본적으로 인덱싱되며 인덱싱을 지정할 필요가 없습니다. 사용자 지정 인덱싱 정책을 정의할 수 있지만 현재 EF에서 지원되지 않으며, EF 지원 없이 Azure Portal을 통해 수행할 수 있습니다. HasIndex 호출은 아무 작업도 수행하지 않았기 때문에 더 이상 허용되지 않습니다.

해결 방법

HasIndex에 대한 모든 호출을 제거합니다.

IncludeRootDiscriminatorInJsonId가 9.0.0-rc.2 이후 HasRootDiscriminatorInJsonId로 이름이 변경됨

추적 문제 #34717

이전 동작

API는 IncludeRootDiscriminatorInJsonId 9.0.0 rc.1에서 도입되었습니다.

새 동작

EF Core 9.0의 최종 릴리스에서 API 이름이 HasRootDiscriminatorInJsonId로 변경됨

이유

다른 관련 API의 이름이 Has 대신 Include로 시작되도록 바뀌었기 때문에 일관성을 위해 이름이 변경되었습니다.

해결 방법

코드가 IncludeRootDiscriminatorInJsonId API를 사용하는 경우 대신 HasRootDiscriminatorInJsonId를 참조하도록 변경하기만 하면 됩니다.