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 호환성이 손상되는 변경에 대한 아래의 별도 섹션을 참조하세요.
주요 변경 내용 | 영향 |
---|---|
보류 중인 모델 변경 내용이 있는 경우 마이그레이션을 적용할 때 예외가 발생합니다 | 높음 |
명시적 트랜잭션 마이그레이션을 적용할 때 |
높음 |
EF.Functions.Unhex() 가 이제 byte[]? 를 반환합니다. |
낮음 |
SqlFunctionExpression의 Null 허용 여부 인수의 arity 유효성이 검사됨 | 낮음 |
ToString() 메서드는 이제 인스턴스에 대해 빈 문자열을 null 반환합니다. |
낮음 |
공유 프레임워크 종속성이 9.0.x로 업데이트되었습니다. | 낮음 |
높은 영향을 주는 변경 내용
보류 중인 모델 변경 내용이 있는 경우 마이그레이션을 적용할 때 예외가 발생합니다.
이전 동작
모델에 마지막 마이그레이션과 비교하여 보류 중인 변경 내용이 있는 경우 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 Core 릴리스에서 더 이상 작동하지 않게 될 가능성이 높습니다. 권장되는 솔루션은 각 공급자에 대해 별도의 마이그레이션 집합을 생성하는
- 마이그레이션은 일부 EF 서비스를 대체하여 동적으로 생성되거나 선택됩니다.
완화: 이 경우 경고는 오탐이므로 억제해야 합니다.
options.ConfigureWarnings(w => w.Ignore(RelationalEventId.PendingModelChangesWarning))
시나리오가 위의 사례에 속하지 않고 새 마이그레이션을 추가할 때마다 동일한 마이그레이션이 생성되거나 빈 마이그레이션이 만들어지며 예외가 계속 발생하는 경우, 작은 재현 프로젝트를 생성하여 새 문제를 등록하고이 프로젝트를 EF 팀과 공유하십시오
명시적 트랜잭션에서 마이그레이션을 적용할 때 예외가 발생됩니다.
이전 동작
복원력 있는 마이그레이션을 적용하기 위해 일반적으로 다음과 같은 패턴이 사용되었습니다.
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부터 Migrate
및 MigrateAsync
호출은 트랜잭션을 시작하고, 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[]?
를 반환합니다.
이전 동작
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 유효성이 검사됨
이전 동작
이전에는 다른 수의 인수와 null 허용 여부 전파 인수를 사용하여 SqlFunctionExpression
을(를) 만들 수 있었습니다.
새 동작
EF Core 9.0부터 EF는 이제 인수 수와 null 허용 여부 전파 인수가 일치하지 않으면 throw됩니다.
이유
일치하는 인수 수와 Null 허용 여부 전파 인수가 없으면 예기치 않은 동작이 발생할 수 있습니다.
해결 방법
argumentsPropagateNullability
에 arguments
와(과) 같은 수의 요소가 있는지 확인합니다. 의심스러운 경우 null 허용 여부 인수에 false
을(를) 사용합니다.
ToString()
메서드는 이제 인스턴스에 대해 빈 문자열을 null
반환합니다.
이전 동작
이전에 EF는 인수 값이 있을 때 메서드에 ToString()
대해 일관되지 않은 결과를 반환했습니다 null
. 예를 들어 값이 ToString()
반환된 속성에서 값이 반환bool?
null
된 null
속성 bool?
이 아닌 식의 경우입니다. null
True
다른 데이터 형식(예: 값 열거형이 빈 문자열을 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.Memory
Microsoft.Extensions.Configuration.Abstractions
Microsoft.Extensions.Logging
Microsoft.Extensions.DependencyModel
패키지를 확인하므로 이러한 어셈블리는 일반적으로 앱과 함께 배포되지 않습니다.
새 동작
EF Core 9.0은 여전히 net8.0을 지원하지만 이제는 9.0.x 버전의 System.Text.Json
, Microsoft.Extensions.Caching.Memory
Microsoft.Extensions.Configuration.Abstractions
Microsoft.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
으로 지정됨
이전 동작
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 키 속성만 포함됨
이전 동작
이전에 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
속성이 키에 매핑됩니다.
이전 동작
이전에 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 동기화는 더 이상 지원되지 않음
이전 동작
이전에는 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 값을 직접 프로젝트해야 함
이전 동작
이전에는 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
한정자를 추가하기만 하면 됩니다.
이제 쿼리 결과에서 정의되지 않은 결과가 자동으로 필터링됨
이전 동작
이전에는 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();
잘못 변환된 쿼리는 더 이상 변환되지 않음
이전 동작
이전에는 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됨
이전 동작
이전에는 EF Cosmos DB 공급자가 HasIndex에 대한 호출을 무시했습니다.
새 동작
HasIndex가 지정된 경우 이제 공급자가 throw됩니다.
이유
Azure Cosmos DB에서 모든 속성은 기본적으로 인덱싱되며 인덱싱을 지정할 필요가 없습니다. 사용자 지정 인덱싱 정책을 정의할 수 있지만 현재 EF에서 지원되지 않으며, EF 지원 없이 Azure Portal을 통해 수행할 수 있습니다. HasIndex 호출은 아무 작업도 수행하지 않았기 때문에 더 이상 허용되지 않습니다.
해결 방법
HasIndex에 대한 모든 호출을 제거합니다.
IncludeRootDiscriminatorInJsonId
가 9.0.0-rc.2 이후 HasRootDiscriminatorInJsonId
로 이름이 변경됨
이전 동작
API는 IncludeRootDiscriminatorInJsonId
9.0.0 rc.1에서 도입되었습니다.
새 동작
EF Core 9.0의 최종 릴리스에서 API 이름이 HasRootDiscriminatorInJsonId
로 변경됨
이유
다른 관련 API의 이름이 Has
대신 Include
로 시작되도록 바뀌었기 때문에 일관성을 위해 이름이 변경되었습니다.
해결 방법
코드가 IncludeRootDiscriminatorInJsonId
API를 사용하는 경우 대신 HasRootDiscriminatorInJsonId
를 참조하도록 변경하기만 하면 됩니다.
.NET