Share via


EF Core 7.0(EF7)의 호환성이 손상되는 변경

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

대상 프레임워크

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

요약

주요 변경 내용 영향
Encrypt의 기본값은 SQL Server 연결의 경우 true로 설정됨 높음
일부 경고는 기본적으로 예외를 다시 throw함 높음
트리거 또는 특정 계산 열이 있는 SQL Server 테이블에는 이제 특별한 EF Core 구성이 필요함 높음
AFTER 트리거이 있는 SQL Server 테이블 및 가상 테이블에는 이제 특별한 EF Core 구성이 필요함 높음
선택적 관계의 분리된 종속 항목이 자동으로 삭제되지 않음 중간
SQL Server TPT 매핑을 사용할 때 테이블 간에 계단식 삭제가 구성됨 중간
미리 쓰기 로깅을 사용하지 않을 때 SQLite에서 사용 중/잠긴 오류 발생 가능성 높아 중간
공급자 값 비교자를 사용하여 키 속성을 구성해야 할 수 있음 낮음
검사 제약 조건 및 기타 테이블 패싯이 이제 테이블에 구성되어 있음 낮음
새 엔터티에서 삭제된 엔터티로의 탐색이 수정되지 않음 낮음
잘못된 공급자가 throw하는 FromSqlRaw 및 관련 메서드 사용 낮음
스캐폴드된 OnConfiguring이 더 이상 IsConfigured를 호출하지 않음 낮음

높은 영향을 주는 변경 내용

Encrypt의 기본값은 SQL Server 연결의 경우 true로 설정됨

추적 문제: SqlClient #1210

Important

이는 Microsoft.Data.SqlClient 패키지의 호환성이 손상되는 심각한 변경입니다. 이 변경을 되돌리거나 완화하기 위해 EF Core에서 수행할 수 있는 작업은 없습니다. Microsoft.Data.SqlClient GitHub 리포지토리로 직접 피드백을 보내거나 Microsoft 지원 전문가에게 문의하여 추가 질문이나 도움을 받으세요.

이전 동작

SqlClient 연결 문자열은 기본적으로 Encrypt=False를 사용합니다. 이렇게 하면 로컬 서버에 유효한 인증서가 없는 개발 머신에서 연결할 수 있습니다.

새 동작

SqlClient 연결 문자열은 기본적으로 Encrypt=True를 사용합니다. 이는 다음을 의미합니다.

  • 서버는 유효한 인증서로 구성해야 함
  • 클라이언트는 이 인증서를 신뢰해야 함

이러한 조건이 충족되지 않으면 SqlException이 throw됩니다. 예시:

서버에 연결했지만 로그인하는 동안 오류가 발생했습니다. (공급자: SSL 공급자, 오류: 0 - 신뢰할 수 없는 기관에서 인증서 체인을 발급했습니다.)

이유

기본적으로 연결이 안전하거나 애플리케이션이 연결되지 않도록 하기 위해 이렇게 변경되었습니다.

해결 방법

계속 진행하는 방법은 3가지가 있습니다.

  1. 서버에 유효한 인증서를 설치합니다. 이 프로세스는 관련된 프로세스이며 인증서를 가져와서 클라이언트에서 신뢰할 수 있는 기관에서 서명했는지 확인해야 합니다.
  2. 서버에 인증서가 있지만 클라이언트에서 신뢰할 수 없는 경우 일반 신뢰 메커니즘 무시를 허용하도록 TrustServerCertificate=True합니다.
  3. 연결 문자열에 Encrypt=False를 명시적으로 추가합니다.

Warning

옵션 2와 3은 둘 다 서버를 잠재적으로 안전하지 않은 상태로 둡니다.

일부 경고는 기본적으로 예외를 다시 throw함

추적 이슈 #29069

이전 동작

EF Core 6.0에서 SQL Server 공급자의 버그로 인해 기본적으로 예외를 throw하도록 구성된 일부 경고가 기록되지만 예외를 throw하지는 않습니다. 이러한 경고는 다음과 같습니다.

EventId 설명
RelationalEventId.AmbientTransactionWarning 애플리케이션은 실제로 무시되었을 때 앰비언트 트랜잭션이 사용될 것으로 예상했을 수 있습니다.
RelationalEventId.IndexPropertiesBothMappedAndNotMappedToTable 인덱스는 일부 속성이 매핑되고 일부는 테이블의 열에 매핑되지 않은 속성을 지정합니다.
RelationalEventId.IndexPropertiesMappedToNonOverlappingTables 인덱스는 겹치지 않는 테이블의 열에 매핑되는 속성을 지정합니다.
RelationalEventId.ForeignKeyPropertiesMappedToUnrelatedTables 외래 키는 관련 테이블에 매핑되지 않는 속성을 지정합니다.

새 동작

EF Core 7.0부터 이러한 경고는 기본적으로 예외가 throw됩니다.

이유

이러한 문제는 수정해야 하는 애플리케이션 코드의 오류를 나타낼 가능성이 매우 높은 문제입니다.

해결 방법

경고의 원인인 기본 문제를 해결합니다.

또는 경고 수준이 로깅만 되거나 완전히 표시되지 않도록 변경할 수 있습니다. 예시:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .ConfigureWarnings(b => b.Ignore(RelationalEventId.AmbientTransactionWarning));

트리거 또는 특정 계산 열이 있는 SQL Server 테이블에는 이제 특별한 EF Core 구성이 필요합니다.

추적 이슈 #27372

이전 동작

이전 버전의 SQL Server 항상 작동하는 덜 효율적인 기술을 통해 변경 내용을 저장했습니다.

새 동작

기본적으로 EF Core는 훨씬 더 효율적인 기술을 통해 변경 내용을 저장합니다. 아쉽게도 대상 테이블에 데이터베이스 트리거 또는 특정 유형의 계산 열이 있는 경우 이 기술은 SQL Server에서 지원되지 않습니다. 자세한 내용은 SQL Server 설명서를 참조하세요.

이유

새 메서드에 연결된 성능이 상당히 향상되어, 기본적으로 사용자에게 제공하는 것이 중요합니다. 이와 동시에, EF Core 애플리케이션에서 데이터베이스 트리거 또는 영향을 받는 계산 열의 사용량은 충분히 낮아, 호환성이 손상되는 변경에 따른 부정적인 결과보다 성능 향상이 클 것으로 예상합니다.

완화 방법

EF Core 8.0부터 "OUTPUT" 절의 사용 여부를 명시적으로 구성할 수 있습니다. 예시:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlOutputClause(false));
}

EF7 이상에서는 대상 테이블에 트리거가 있는 경우 EF Core에 이를 알릴 수 있으며, EF는 덜 효율적인 이전 기술로 되돌립니다. 이 작업은 다음과 같이 해당 엔터티 형식을 구성하여 수행할 수 있습니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.HasTrigger("SomeTrigger"));
}

이렇게 하면 실제로 EF Core가 어떤 방식으로든 트리거를 만들거나 관리하지 않습니다. 현재는 트리거가 테이블에 있다는 것만 EF Core에 알릴 뿐입니다. 결과적으로 모든 트리거 이름을 사용할 수 있습니다. 트리거를 지정하면 테이블에 실제로 트리거가 없더라도 이전 동작을 되돌릴 수 있습니다.

테이블의 대부분 또는 전부에 트리거가 있는 경우 다음 모델 빌드 규칙을 사용하여 모든 모델의 테이블에 대해 더 새롭고 효율적인 기술을 사용하지 않을 수 있습니다.

public class BlankTriggerAddingConvention : IModelFinalizingConvention
{
    public virtual void ProcessModelFinalizing(
        IConventionModelBuilder modelBuilder,
        IConventionContext<IConventionModelBuilder> context)
    {
        foreach (var entityType in modelBuilder.Metadata.GetEntityTypes())
        {
            var table = StoreObjectIdentifier.Create(entityType, StoreObjectType.Table);
            if (table != null
                && entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(table.Value) == null)
                && (entityType.BaseType == null
                    || entityType.GetMappingStrategy() != RelationalAnnotationNames.TphMappingStrategy))
            {
                entityType.Builder.HasTrigger(table.Value.Name + "_Trigger");
            }

            foreach (var fragment in entityType.GetMappingFragments(StoreObjectType.Table))
            {
                if (entityType.GetDeclaredTriggers().All(t => t.GetDatabaseName(fragment.StoreObject) == null))
                {
                    entityType.Builder.HasTrigger(fragment.StoreObject.Name + "_Trigger");
                }
            }
        }
    }
}

ConfigureConventions를 재정의하여 DbContext에 대한 규칙을 사용합니다.

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Add(_ => new BlankTriggerAddingConvention());
}

이렇게 하면 각 테이블에 대해 수동으로 수행하는 대신 모델의 모든 테이블에서 HasTrigger를 효과적으로 호출합니다.

AFTER 트리거 및 가상 테이블이 있는 SQLite 테이블에는 이제 특별한 EF Core 구성이 필요함

추적 이슈 #29916

이전 동작

이전 버전의 SQLite 공급자는 항상 작동하는 덜 효율적인 기술을 통해 변경 내용을 저장했습니다.

새 동작

기본적으로 EF Core는 이제 RETURNING 절을 사용하여 보다 효율적인 기술을 통해 변경 내용을 저장합니다. 아쉽게도 대상 테이블에 AFTER 트리거 데이터베이스가 있거나 가상이거나 이전 버전의 SQLite가 사용되는 경우 이 기술은 SQLite에서 지원되지 않습니다. 자세한 내용은 SQLite 설명서를 참조하세요.

이유

새 메서드에 연결된 간소화 및 성능이 상당히 향상되어, 기본적으로 사용자에게 제공하는 것이 중요합니다. 이와 동시에, EF Core 애플리케이션에서 데이터베이스 트리거 및 가상 테이블의 사용량은 충분히 낮아, 호환성이 손상되는 변경에 따른 부정적인 결과보다 성능 향상이 클 것으로 예상합니다.

완화 방법

EF Core 8.0에서는 이전의 덜 효율적인 SQL로 명시적으로 되돌리기 위해 UseSqlReturningClause 메서드가 도입되었습니다. 예시:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .ToTable(tb => tb.UseSqlReturningClause(false));
}

아직 EF Core 7.0을 사용하고 있다면 컨텍스트 구성에 다음 코드를 삽입하여 전체 애플리케이션에 대해 이전 메커니즘으로 되돌릴 수 있습니다.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

중간 영향을 주는 변경 내용

선택적 관계의 분리된 종속 항목이 자동으로 삭제되지 않음

추적 이슈 #27217

이전 동작

외래 키가 null 허용인 경우 관계는 선택 사항입니다. 외래 키를 null로 설정하면 관련 주체 엔터티 없이 종속 엔터티가 존재할 수 있습니다. 기본값은 아니지만 계단식 삭제를 사용하도록 선택적 관계를 구성할 수 있습니다.

선택적 종속 항목은 외래 키를 null로 설정하거나 탐색을 선택 취소하여 보안 주체에서 분리할 수 있습니다. EF Core 6.0에서는 계단식 삭제를 위해 관계가 구성되었을 때 종속 항목이 삭제됩니다.

새 동작

EF Core 7.0부터 종속 항목이 더 이상 삭제되지 않습니다. 보안 주체가 삭제된 경우 계단식 삭제가 관계에 대해 구성되었으므로 종속 항목은 여전히 삭제됩니다.

이유

종속 항목은 보안 주체와의 관계 없이 존재할 수 있으므로 관계를 끊으면 엔터티가 삭제되지 않아야 합니다.

해결 방법

종속 항목을 명시적으로 삭제할 수 있습니다.

context.Remove(blog);

또는 SaveChanges 보안 주체 참조 없이 종속 항목을 삭제하도록 재정의하거나 가로챌 수 있습니다. 예시:

context.SavingChanges += (c, _) =>
    {
        foreach (var entry in ((DbContext)c!).ChangeTracker
            .Entries<Blog>()
            .Where(e => e.State == EntityState.Modified))
        {
            if (entry.Reference(e => e.Author).CurrentValue == null)
            {
                entry.State = EntityState.Deleted;
            }
        }
    };

SQL Server TPT 매핑을 사용할 때 테이블 간에 계단식 삭제가 구성됩니다.

추적 이슈 #28532

이전 동작

TPT 전략을 사용하여 상속 계층 구조를 매핑할 때 기본 테이블에는 해당 엔터티의 실제 형식에 관계없이 저장된 모든 엔터티에 대한 행이 포함되어야 합니다. 기본 테이블의 행을 삭제하면 다른 모든 테이블의 행이 삭제됩니다. EF Core는 이에 대한 계단식 삭제를 구성합니다.

EF Core 6.0에서 SQL Server 데이터베이스 공급자의 버그로 인해 이러한 계단식 삭제가 생성되지 않았습니다.

새 동작

EF Core 7.0부터는 다른 데이터베이스와 마찬가지로 SQL Server 대해 계단식 삭제가 생성됩니다.

이유

기본 테이블에서 TPT의 하위 테이블로 계단식 삭제를 사용하면 기본 테이블의 행을 삭제하여 엔터티를 삭제할 수 있습니다.

해결 방법

대부분의 경우 이 변경으로 인해 문제가 발생하지 않아야 합니다. 그러나 테이블 사이에 여러 개의 계단식 동작이 구성된 경우 SQL Server는 매우 제한적입니다. 즉, TPT 매핑의 테이블 간에 기존 계단식 관계가 있는 경우 SQL Server에서 다음 오류가 발생할 수 있습니다.

Microsoft.Data.SqlClient.SqlException: DELETE 문이 REFERENCE 제약 조건 “FK_Blogs_People_OwnerId”와 충돌합니다. 데이터베이스 “Scratch”, 테이블 “dbo.Blogs”, 열 ‘OwnerId’에서 충돌이 발생했습니다. 문이 종료되었습니다.

예를 들어 이 모델은 계단식 관계의 주기를 만듭니다.

[Table("FeaturedPosts")]
public class FeaturedPost : Post
{
    public int ReferencePostId { get; set; }
    public Post ReferencePost { get; set; } = null!;
}

[Table("Posts")]
public class Post
{
    public int Id { get; set; }
    public string? Title { get; set; }
    public string? Content { get; set; }
}

이 중 하나는 서버에서 계단식 삭제를 사용하지 않도록 구성해야 합니다. 예를 들어 명시적 관계를 변경하려면 다음을 수행합니다.

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne(e => e.ReferencePost)
    .WithMany()
    .OnDelete(DeleteBehavior.ClientCascade);

또는 TPT 매핑에 대해 만든 암시적 관계를 변경하려면 다음을 수행합니다.

modelBuilder
    .Entity<FeaturedPost>()
    .HasOne<Post>()
    .WithOne()
    .HasForeignKey<FeaturedPost>(e => e.Id)
    .OnDelete(DeleteBehavior.ClientCascade);

미리 쓰기 로깅을 사용하지 않을 때 SQLite에서 사용 중/잠긴 오류 발생 가능성 높아

이전 동작

이전 버전의 SQLite 공급자는 테이블이 잠기거나 사용 중이고 WAL(미리 쓰기 로깅)을 사용할 수 없을 때 자동으로 다시 시도할 수 있는 효율성이 낮은 기술을 통해 변경 내용을 저장했습니다.

새 동작

기본적으로 EF Core는 이제 RETURNING 절을 사용하여 보다 효율적인 기술을 통해 변경 내용을 저장합니다. 아쉽게도 이 기술은 사용 중/잠긴 경우 자동으로 다시 시도할 수 없습니다. 미리 쓰기 로깅을 사용하지 않는 다중 스레드 애플리케이션(예: 웹앱)에서는 이러한 오류가 발생하는 것이 일반적입니다.

이유

새 메서드에 연결된 간소화 및 성능이 상당히 향상되어, 기본적으로 사용자에게 제공하는 것이 중요합니다. EF Core에서 만든 데이터베이스는 기본적으로 미리 쓰기 로깅을 사용하도록 설정합니다. 또한 SQLite 팀은 기본적으로 미리 쓰기 로깅을 사용하도록 설정하는 것이 좋습니다.

완화 방법

가능하면 데이터베이스에서 미리 쓰기 로깅을 사용하도록 설정해야 합니다. EF에서 데이터베이스를 만든 경우 이미 해당되는 경우입니다. 그렇지 않은 경우 다음 명령을 실행하여 미리 쓰기 로깅을 사용하도록 설정할 수 있습니다.

PRAGMA journal_mode = 'wal';

어떤 이유로 미리 쓰기 로깅을 사용하도록 설정할 수 없는 경우 컨텍스트 구성에 다음 코드를 삽입하여 전체 애플리케이션에 대한 이전 메커니즘으로 되돌릴 수 있습니다.

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .UseSqlite(...)
        .ReplaceService<IUpdateSqlGenerator, SqliteLegacyUpdateSqlGenerator>();

낮은 영향을 주는 변경 내용

공급자 값 비교자를 사용하여 키 속성을 구성해야 할 수 있음

추적 이슈 #27738

이전 동작

EF Core 6.0에서는 엔터티 형식의 속성에서 직접 가져온 키 값이 변경 내용을 저장할 때 키 값을 비교하는 데 사용되었습니다. 이렇게 하면 이러한 속성에 구성된 사용자 지정 값 비교자를 사용할 수 있습니다.

새 동작

EF Core 7.0부터 데이터베이스 값이 이러한 비교에 사용됩니다. 이것은 대부분의 경우에 "작동"합니다. 그러나 속성이 사용자 지정 비교자를 사용하고 있고 해당 비교자를 데이터베이스 값에 적용할 수 없는 경우 아래와 같이 "공급자 값 비교자"가 필요할 수 있습니다.

이유

다양한 엔터티 분할 및 테이블 분할로 인해 동일한 데이터베이스 열에 매핑된 여러 속성이 발생할 수 있으며 그 반대의 경우도 마찬가지입니다. 이렇게 하려면 데이터베이스에서 사용할 값으로 변환한 후 값을 비교해야 합니다.

해결 방법

공급자 값 비교자를 구성합니다. 예를 들어 값 개체가 키로 사용되고 해당 키의 비교자가 대/소문자를 구분하지 않는 문자열 비교를 사용하는 경우를 고려합니다.

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer);

데이터베이스 값(문자열)은 BlogKey 형식에 대해 정의된 비교자를 직접 사용할 수 없습니다. 따라서 대/소문자를 구분하지 않는 문자열 비교를 위한 공급자 비교자를 구성해야 합니다.

var caseInsensitiveComparer = new ValueComparer<string>(
    (l, r) => string.Equals(l, r, StringComparison.OrdinalIgnoreCase),
    v => v.ToUpper().GetHashCode(),
    v => v);

var blogKeyComparer = new ValueComparer<BlogKey>(
    (l, r) => string.Equals(l.Id, r.Id, StringComparison.OrdinalIgnoreCase),
    v => v.Id.ToUpper().GetHashCode(),
    v => v);

var blogKeyConverter = new ValueConverter<BlogKey, string>(
    v => v.Id,
    v => new BlogKey(v));

modelBuilder.Entity<Blog>()
    .Property(e => e.Id).HasConversion(
        blogKeyConverter, blogKeyComparer, caseInsensitiveComparer);

검사 제약 조건 및 기타 테이블 패싯이 이제 테이블에 구성되어 있음

추적 이슈 #28205

이전 동작

EF Core 6.0, HasCheckConstraint, HasComment, 및 IsMemoryOptimized는 엔터티 형식 작성기에서 직접 호출되었습니다. 예시:

modelBuilder
    .Entity<Blog>()
    .HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023");

modelBuilder
    .Entity<Blog>()
    .HasComment("It's my table, and I'll delete it if I want to.");

modelBuilder
    .Entity<Blog>()
    .IsMemoryOptimized();

새 동작

EF Core 7.0부터 테이블 작성기에서 이러한 메서드가 대신 호출됩니다.

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasCheckConstraint("CK_Blog_TooFewBits", "Id > 1023"));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.HasComment("It's my table, and I'll delete it if I want to."));

modelBuilder
    .Entity<Blog>()
    .ToTable(b => b.IsMemoryOptimized());

기존 메서드가 Obsolete로 표시되었습니다. 현재 새 메서드와 동일한 동작이 있지만 이후 릴리스에서 제거될 예정입니다.

이유

이러한 패싯은 테이블에만 적용됩니다. 매핑된 뷰, 함수 또는 저장 프로시저에는 적용되지 않습니다.

해결 방법

위와 같이 테이블 작성기 메서드를 사용합니다.

추적 이슈 #28249

이전 동작

EF Core 6.0에서 추적 쿼리에서 또는 DbContext연결하여 새 엔터티를 추적하면 Deleted 상태의 관련 엔터티로의 및 엔터티로부터의 탐색이 수정됩니다.

새 동작

EF Core 7.0부터 Deleted 엔터티로의 및 엔터티로부터의 탐색은 수정되지 않습니다.

이유

엔터티가 Deleted로 표시되면 삭제되지 않은 엔터티와 연결하는 것은 거의 의미가 없습니다.

해결 방법

엔터티를 Deleted로 표시하기 전에 엔터티를 쿼리하거나 연결하거나 삭제된 엔터티에서 탐색 속성을 수동으로 설정합니다.

추적 이슈 #26502

이전 동작

EF Core 6.0에서 관계형 공급자를 사용할 때 Azure Cosmos DB FromSqlRaw 확장 메서드를 사용하거나 Azure Cosmos DB 공급자를 사용할 때 관계형 FromSqlRaw 확장 메서드를 사용하면 자동으로 실패할 수 있습니다. 마찬가지로, 메모리 내 공급자에서 관계형 메서드를 사용하는 것은 자동으로 작동하지 않습니다.

새 동작

EF Core 7.0부터 다른 공급자의 한 공급자를 위해 설계된 확장 메서드를 사용하면 예외가 throw됩니다.

이유

모든 상황에서 올바르게 작동하려면 올바른 확장 메서드를 사용해야 합니다.

해결 방법

사용 중인 공급자에 대해 올바른 확장 메서드를 사용합니다. 여러 공급자를 참조하는 경우 확장 메서드를 정적 메서드로 호출합니다. 예시:

var result = CosmosQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToList();

또는

var result = RelationalQueryableExtensions.FromSqlRaw(context.Blogs, "SELECT ...").ToList();

스캐폴드된 OnConfiguring이 더 이상 IsConfigured를 호출하지 않음

추적 이슈 #4274

이전 동작

EF Core 6.0에는 기존 데이터베이스에서 스캐폴드된 DbContext 형식에는 IsConfigured에 대한 호출이 포함되어 있습니다. 예시:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    if (!optionsBuilder.IsConfigured)
    {
#warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see http://go.microsoft.com/fwlink/?LinkId=723263.
        optionsBuilder.UseNpgsql("MySecretConnectionString");
    }
}

새 동작

EF Core 7.0부터는 IsConfigured에 대한 호출이 더 이상 포함되지 않습니다.

이유

경우에 따라 데이터베이스 공급자가 DbContext 내에서 구성되지만 컨텍스트가 아직 구성되지 않은 경우에만 매우 제한된 시나리오가 있습니다. 대신 OnConfiguring을 여기에 두면 컴파일 시간 경고에도 불구하고 중요한 정보가 포함된 연결 문자열이 코드에 남아 있을 가능성이 높아집니다. 따라서 특히 --no-onconfiguring(.NET CLI) 또는 -NoOnConfiguring(Visual Studio 패키지 관리자 콘솔) 플래그를 사용하여 OnConfiguring 메서드의 스캐폴딩을 방지할 수 있으며, 실제로 필요한 경우 사용자 지정 가능한 템플릿을 사용하여 IsConfigured를 다시 추가할 수 있다는 점을 감안할 때 이 코드를 제거하는 것이 더 안전하고 깨끗한 것으로 간주되었습니다.

해결 방법

다음 중 하나

  • 기존 데이터베이스에서 스캐폴딩할 때 --no-onconfiguring(.NET CLI) 또는 -NoOnConfiguring(Visual Studio 패키지 관리자 콘솔) 인수를 사용합니다.
  • T4 템플릿을 사용자 지정하여 IsConfigured에 대한 호출을 다시 추가합니다.