티스토리 뷰

반응형

2020년 11월 10일 Entity Framework Core 5.0가 릴리즈 되었습니다. 한동안 서비스를 이용해서 데이터를 받아오기만 하다보니 Entity Framework에 대해서 관심을 가지기 힘들었었는데, 얼마전에 포팅했던 UnoContoso앱에서 EF를 다시 사용해 보고 너무 마음에 들어서 다시 관심을 가져 보려고 합니다. 앞으로 자주 EF Core에 대한 내용을 올리도록 하겠습니다.

 

Announcing the Release of EF Core 5.0 | .NET Blog (microsoft.com)

 

Announcing the Release of EF Core 5.0 | .NET Blog

Announcing the release of EF Core 5.0, a full featured cross-platform library for data access supporting Many-to-Many, Table-per-Type & more.

devblogs.microsoft.com

What’s new in EF Core 5.0

EF Core의 초기 릴리스는 유연하고 확장 가능한 아키텍처를 구축하는 데 중점을 두었습니다. EF Core 3.1에서 팀은 몇 가지 주요 변경 사항과 정밀 검사된 쿼리 파이프 라인을 사용하여 이 아키텍처를 축소했습니다. 3.1의 기반을 통해 팀과 커뮤니티는 EF Core 5.0에 대한 놀라운 새 기능 세트를 제공 할수 있었습니다. 81개의 중요한 개선 사항 중 일부는 다음과 같습니다. 모든 개선 사항에 대해서는 여기를 참고합니다.

 

주소의 en-us를 ko-kr로 변경하시면 한글로 확인하실 수 있습니다.

 

  • Many-to-many relationship mapping : EF Core 5.0은 조인 테이블을 명시적으로 매핑하지 않고도 many-to-many 관계를 지원합니다
  • Table-per-type inheritance mapping : 상속 계층 구조의 각 .NET Type을 다른 데이터베이스 테이블에 매핑 할 수도 있습니다. 이를 유형별 테이블 매핑(TPT)이라고 합니다.
  • IndexAttribute to map indexes without the fluent API : 새 IndexAttribute를 엔터티 형식에 배치하여, 단일컬럼에 대한 인덱스를 지정할 수 있습니다.
  • Database collations : 데이터베이스에 대한 기본 데이터 정렬을 EF 모델에서 지정할 수 있습니다. 이는 데이터베이스가 생성 될 때 데이터 정렬을 설정하기 위해 마이그레이션으로 진행됩니다.
  • Filtered Include : Include 메서드를 이용할 때 포함된 엔터티의 필터링을 지원합니다.
  • Simple logging : EF Core에서 단순 로깅을 사용하여 애플리케이션을 개발하고 디버깅하는 동안 로그를 쉽게 얻을 수 있습니다.
  • Exclude tables from migrations : 모델이 변경되었을 때 마이그레이션을 생성하면 여러개의 DbContext에서 업데이트를 시도하게되는데, 이를 방지하기 위해 컨텍스트 중 하나에 대한 모델이 마이그레이션 중 특정 테이블을 제외하도록 구성 할 수 있습니다.
  • Split queries for related collections : 관련 컬렉션을 포함하는 단일 LINQ쿼리를 여러 SQL 쿼리로 분할 할 수 있습니다. 이 방법은 성능을 향상 시킬 수도 있지만, 결과의 불일치가 발생할 수도 있습니다.
  • Event counters : .NET 이벤트 카운터는 애플리케이션에서 성능 메트릭을 효율적으로 노출하는 방법입니다.
  • SaveChanges interception and events : SaveChanges가 호출 될 때 트리거되는 .NET 이벤트와 EF Core 인터셉터가 모두 도입되었습니다.
  • Required 1:1 dependents : 기존 일대일 관계의 종속은 유지는 옵션사항으로 간주되었습니다. EF 5.0에서는 필수 종속 항목으로 구성할 수 있습니다.
  • Migrations scripts with transactions : 마이그레이션에서 생성된 SQL 스크립트에는 이제 마이그레이션에 적합한 트랜잭션을 시작하고 커밋하는 문이 포함됩니다.
  • Rebuild SQLite tables as needed in migrations : 다른 데이터베이스에 비해 SQLite는 스키마 조작 기능이 비교적 제한적입니다. EF Core 5.0 마이그레이션은 이제 필요한 스키마 변경에 대한 테이블 자동 다시 빌드를 지원합니다.
  • Mapping for table-valued functions : .NET 메서드를 TVF(테이블 반환 함수)에 매핑하기 위한 최고급 지원이 포함되어 있습니다.
  • DbContextFactory support for dependency injection : AddDbContextFactory 및 AddPooledDbContextFactory를 도입하여 애플리케이션의 종속성 주입 컨테이너에 DbContext인스턴스를 만들기 위한 팩토리를 등록합니다.
  • ChangeTracker.Clear to stop tracking all entities : 추적된 모든 엔터티의 DbContext를 지우는 ChangeTracker.Clear()가 도입되었습니다. 이는 DbContext 인스턴스의 상태를 재설정해야하는 경우 새로운 Clear() 메서드를 사용하는 것이 모든 엔터티를 대량 분리하는 것보다 더 성능이 좋고 강력합니다.
  • Improved Cosmos configuration : Cosmos 및 Cosmos 연결 구성을 개선했습니다.
  • Change-tracking proxies : INotifyPropertyChanging 및 INotifyPropertyChanged를 자동으로 구현하는 런타임 프록시를 생성 할 수 있습니다.
  • Property bags : 동일한 CLR 유형을 여러 다른 엔터티 유형에 매핑 할 수 있습니다.

Julie Lerman: Simple logging

EF Core는 항상 Microsoft.Extensions.Logging 인프라와 통합되었습니다. 이 로깅 형식은 강력하고 확장 가능하지만, 외부 종속성 및 구성이 필요했습니다. EF Core 5.0은 추가 종속성을 설치하지 않고도, 개발 및 디버깅하는 동안 로그를 얻는 간단한 방법으로 LogTo 메서드를 도입했습니다.

 

LogTo는 DbContext 인스턴스를 구성 할 때 호출됩니다. 이 구성은 일반적으로 DbContext.OnConfiguring 재정의에서 수행됩니다. 예를 들면 :

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    => optionsBuilder
        .EnableSensitiveDataLogging()
        .EnableDetailedErrors()
        .LogTo(Console.WriteLine);

또는 AddDbContext의 일부로 또는 DbContext 생성자에 전달할 DbContextOptions 인스턴스를 만들 때 LogTo를 호출 할 수 있습니다. 예를 들면 :

serviceCollection.AddDbContext<SomeDbContext>(
    b => b.UseSqlServer(Your.ConnectionString)
        .EnableSensitiveDataLogging()
        .EnableDetailedErrors()
        .LogTo(Console.WriteLine));

두 예 모두 콘솔에 대한 로깅을 설정하고 최상의 디버깅 환경을 위해 민감한 데이터 로깅 및 자세한 오류를 표시합니다. 예를 들면 :

warn: 11/4/2020 12:59:56.097 CoreEventId.SensitiveDataLoggingEnabledWarning[10400] (Microsoft.EntityFrameworkCore.Infrastructure)
      Sensitive data logging is enabled. Log entries and exception messages may include sensitive application data; this mode should only be enabled during development.
info: 11/4/2020 12:59:56.190 CoreEventId.ContextInitialized[10403] (Microsoft.EntityFrameworkCore.Infrastructure)
      Entity Framework Core 5.0.0-rc.2.20475.6 initialized 'SomeDbContext' using provider 'Microsoft.EntityFrameworkCore.SqlServer' with options: SensitiveDataLoggingEnabled
dbug: 11/4/2020 12:59:56.221 RelationalEventId.ConnectionOpening[20000] (Microsoft.EntityFrameworkCore.Database.Connection)
      Opening connection to database 'Test' on server '(local)'.

아래와 같은 기능을 제공합니다.

  • 디버그 창 또는 파일에 로깅
  • 로그 필터링
  • 메시지 내용 및 서식

Diego Vega: Many-to-many (M2M) relationships

EF Core 5.0은 조인 테이블을 명시적으로 매핑하지 않고도 many-to-many 관계를 지원합니다.

public class Post
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Tag> Tags { get; set; }
}

public class Tag
{
    public int Id { get; set; }
    public string Text { get; set; }
    public ICollection<Post> Posts { get; set; }
}

위 두개의 모델을 생성하면 EF Core 5.0에서는 관례상 다대다 관계로 인식합니다. 이는 OnModelCreating에 코드가 필요하지 않음을 의미합니다.

public class BlogContext : DbContext
{
    public DbSet<Post> Posts { get; set; }
    public DbSet<Blog> Blogs { get; set; }
}

마이그레이션(또는 ensureCreated)을 사용하여 데이터베이스를 만드는 경우 EF Core는 자동으로 조인 테이블을 만듭니다. 예를 들어 모델의 SQL Server에서 EF Core는 다음을 생성합니다.

CREATE TABLE [Posts] (
    [Id] int NOT NULL IDENTITY,
    [Name] nvarchar(max) NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]));

CREATE TABLE [Tags] (
    [Id] int NOT NULL IDENTITY,
    [Text] nvarchar(max) NULL,
    CONSTRAINT [PK_Tags] PRIMARY KEY ([Id]));

CREATE TABLE [PostTag] (
    [PostsId] int NOT NULL,
    [TagsId] int NOT NULL,
    CONSTRAINT [PK_PostTag] PRIMARY KEY ([PostsId], [TagsId]),
    CONSTRAINT [FK_PostTag_Posts_PostsId] FOREIGN KEY ([PostsId]) REFERENCES [Posts] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_PostTag_Tags_TagsId] FOREIGN KEY ([TagsId]) REFERENCES [Tags] ([Id]) ON DELETE CASCADE);

CREATE INDEX [IX_PostTag_TagsId] ON [PostTag] ([TagsId]);

Post와 Tag를 만들고 연결하면 조인 테이블 업데이트가 자동으로 발생합니다. 예를 들면

var beginnerTag = new Tag {Text = "Beginner"};
var advancedTag = new Tag {Text = "Advanced"};
var efCoreTag = new Tag {Text = "EF Core"};

context.AddRange(
    new Post {Name = "EF Core 101", Tags = new List<Tag> {beginnerTag, efCoreTag}},
    new Post {Name = "Writing an EF database provider", Tags = new List<Tag> {advancedTag, efCoreTag}},
    new Post {Name = "Savepoints in EF Core", Tags = new List<Tag> {beginnerTag, efCoreTag}});

context.SaveChanges();

Post와 Tag를 삽입 한 후 EF는 조인 테이블에 자동으로 행을 만듭니다. SQL Server에서는

Executed DbCommand (8ms) [Parameters=[@p6='1', @p7='1', @p8='1', @p9='2', @p10='2', @p11='2', @p12='2', @p13='3', @p14='3', @p15='1', @p16='3', @p17='2'], CommandType='Text', CommandTimeout='30']
      SET NOCOUNT ON;
      INSERT INTO [PostTag] ([PostsId], [TagsId])
      VALUES (@p6, @p7),
      (@p8, @p9),
      (@p10, @p11),
      (@p12, @p13),
      (@p14, @p15),
      (@p16, @p17);

쿼리의 경우에도 Include 및 기타 쿼리 작업은 일반적인 관계와 마찬가지로 사용할 수 있습니다. 예를 들면

foreach (var post in context.Posts.Include(e => e.Tags))
{
    Console.Write($"Post "{post.Name}" has tags");

    foreach (var tag in post.Tags)
    {
        Console.Write($" '{tag.Text}'");
    }
}

위의 내용을 SQL을 이용하는 경우는

SELECT [p].[Id], [p].[Name], [t0].[PostsId], [t0].[TagsId], [t0].[Id], [t0].[Text]
FROM [Posts] AS [p]
LEFT JOIN (
    SELECT [p0].[PostsId], [p0].[TagsId], [t].[Id], [t].[Text]
    FROM [PostTag] AS [p0]
    INNER JOIN [Tags] AS [t] ON [p0].[TagsId] = [t].[Id]
) AS [t0] ON [p].[Id] = [t0].[PostsId]
ORDER BY [p].[Id], [t0].[PostsId], [t0].[TagsId], [t0].[Id]

EF6와 달리 EF Core는 조인 테이블의 전체 사용자 지정을 허용합니다. 예를 들어 아래 코드는 조인 엔터티에 대한 탐색도 포함하고 조인 엔터티에 페이로드 속성이 포함 된 다대다 관계를 구성합니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Post>()
        .HasMany(p => p.Tags)
        .WithMany(p => p.Posts)
        .UsingEntity<PostTag>(
            j => j.HasOne(pt => pt.Tag).WithMany().HasForeignKey(pt => pt.TagId),
            j => j.HasOne(pt => pt.Post).WithMany().HasForeignKey(pt => pt.PostId),
            j =>
            {
                j.Property(pt => pt.PublicationDate).HasDefaultValueSql("CURRENT_TIMESTAMP");
                j.HasKey(t => new { t.PostId, t.TagId });
            });
}

다대다 관계에 대한 더 자세한 사항은 여기를 참고합니다.

Jon P Smith: ChangeTracker.Clear()

EF Core 릴리스를 개발할 때 팀은 큰 기능을 구현할뿐만 아니라 사용 편의성 개선도 많이 구현합니다. 새로운 DbContext.ChangeTracker.Clear () 메서드는 이러한 개선 사항 중 하나입니다. 현재 추적중인 모든 엔터티가 한번에 분리되도록 EF 변경 추적기를 지웁니다. 예를 들면 :

using (var context = new BlogContext())
{
    // A normal tracking query brings entities into the context
    var postsAndTags = context.Posts.Include(e => e.Tags).ToList();
    Debug.Assert(context.ChangeTracker.Entries().Count() == 12);

    // These can then used for one or more updates
    postsAndTags.First().Name = "EF Core 102";
    context.SaveChanges();
    Debug.Assert(context.ChangeTracker.Entries().Count() == 12);

    // All tracked entities can then be detached
    context.ChangeTracker.Clear();
    Debug.Assert(context.ChangeTracker.Entries().Count() == 0);
}

이 예제에서 ChangeTracker.Clear () 호출은 일반적으로 각 작업 단위에 대해 새로운 DbContext 인스턴스를 만드는 모범 사례를 사용할 때는 필요하지 않습니다. 그러나 때로는 애플리케이션 아키텍처로 인해 각 작업 단위에 새 DbContext를 사용하기가 어려워 계속 유지를 해야 할 수 있습니다. 이 경우 ChangeTracker.Clear()를 사용하는 것이 각각의 모든 엔티티를 분리하는 것보다 성능이 뛰어나고 강력합니다.

Erik Ejlskov Jensen: Improved database-first scaffolding

EF Core 5.0에는 데이터베이스 우선 환경을 위한 DbContext의 스캐폴딩 (즉, 리버스 엔지니어링)에 대한 많은 개선 사항이 포함되어 있습니다. 이러한 기능은 EF와 함께 제공되는 명령 줄 도구 또는 Erik의 시각적 EF Core Power Tools와 같은 커뮤니티 프로젝트에서 모두 사용할 수 있습니다. 다음 섹션에서는 몇 가지 예를 보여줍니다.

Scaffold to custom namespaces

EFCore 5.0은 모든 스캐폴딩 된 클래스에 대한 네임 스페이스 재정의를 지원합니다. 또한 원하는 경우 DbContext 클래스에 대해 다른 네임 스페이스를 구성 할 수 있습니다. 예를 들면 :

dotnet ef dbcontext scaffold ... --namespace Your.Namespace --context-namespace Your.DbContext.Namespace

Stop scaffolding the connection string

기본적으로 EF Core는 생성 된 DbContext에 대한 OnConfiguring 호출에 스캐폴딩 된 데이터베이스에 대한 연결 문자열을 포함합니다. 그러나 이것은 이미 다른 방식으로 DbContext를 구성한 응용 프로그램에 대해 실망스러울 수 있습니다. 예를 들어 ASP.NET Core 애플리케이션에서는 그 것이 AddDbContext 내부에 있습니다. EF Core 5.0은 OnConfiguring에 대한 호출을 포함하지 않고 DbContext 스캐폴딩을 지원합니다. 예를 들면 :

dotnet ef dbcontext scaffold ... --no-onconfiguring

Pluralization

EF Core는 이제 Humanizer와 통합되어 데이터베이스에서 스캐폴딩 할 때 기본적으로 복수화를 제공합니다. 이 모든 것을 종합하면 다음은 사용자 정의 네임 스페이스를 사용하고 OnConfiguring을 사용하지 않고 기본 복수화 지원을 사용하는 예제 명령입니다.

dotnet ef dbcontext scaffold 'Server=(local);Database=Blogs;User Id=arthur;Password=Unicorns4All' 
 Microsoft.EntityFrameworkCore.SqlServer --namespace Blogs.Entities 
 --context-namespace Blogs.Context --no-onconfiguring --data-annotations

생성된 결과는 다음과 같습니다.

#nullable disable

namespace Blogs.Context
{
    public partial class BlogsContext : DbContext
    {
        public BlogsContext()
        {
        }

        public BlogsContext(DbContextOptions<BlogsContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Blog> Blogs { get; set; }
        public virtual DbSet<Post> Posts { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            OnModelCreatingPartial(modelBuilder);
        }

        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }
}
#nullable disable

namespace Blogs.Entities
{
    [Index(nameof(BlogId), Name = "IX_Posts_BlogId")]
    public partial class Post
    {
        [Key]
        public int Id { get; set; }
        public string Title { get; set; }
        public string Content { get; set; }
        public int? BlogId { get; set; }

        [ForeignKey(nameof(BlogId))]
        [InverseProperty("Posts")]
        public virtual Blog Blog { get; set; }
    }
}
#nullable disable

namespace Blogs.Entities
{
    public partial class Blog
    {
        public Blog()
        {
            Posts = new HashSet<Post>();
        }

        [Key]
        public int Id { get; set; }
        public string Name { get; set; }

        [InverseProperty(nameof(Post.Blog))]
        public virtual ICollection<Post> Posts { get; set; }
    }
}
  • DbSet 속성 이름은 복수형입니다.
  • 엔터티 형식은 한 네임 스페이스에 있고 DbContext는 다른 네임 스페이스에 있습니다.
  • 내 연결 문자열을 포함하는 OnConfiguring 메서드가 없습니다.
  • OnModelCreating에서 코드를 생성하는 대신 새 IndexAttribute가 사용됩니다.
  • #nullable 비활성화는 EF Core가 현재 nullable 참조 형식으로 리버스 엔지니어링하지 않기 때문에 생성됩니다.

리버스엔지니어링에 대한 더 자세한 사항은 여기를 참고합니다.

Learn more

  • 공식 문서에는 시작 안내서부터 고급 기능 문서까지 모든 것이 포함되어 있습니다.
  • EF Core 주간 업데이트의 최신 변경 사항 유지
  • 팀은 게스트, 뉴스 및 데모를 포함하여 몇 주마다 커뮤니티 스탠드 업을 실시간 스트리밍합니다.
  • GitHub 또는 Stack Overflow에 질문하기
  • Julie, Jon, Erik 등과 같은 EF Core에 대한 훌륭한 책, 온라인 과정 및 블로그 게시물이 많이 있습니다. (정말 좋은 것을 찾으면 알려 주시면 커뮤니티 스탠드 업에서 소개하겠습니다.)

How to get EF Core 5.0

EF Core 5.0에는 .NET Standard 2.1 플랫폼이 필요합니다. 즉, EF Core 5.0은 .NET Core 3.1 또는 .NET 5와 .NET Standard 2.1을 지원하는 다른 플랫폼에서 실행됩니다. EF Core 5.0은 .NET Framework에서 실행되지 않습니다.

 

EF Core 5.0은 NuGet 패키지 집합으로 독점적으로 배포됩니다. 예를 들어 SQL Server 공급자를 프로젝트에 추가하려면 dotnet 도구를 사용하여 다음 명령을 사용할 수 있습니다.

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 5.0.0

PackagePurpose

Package Purpose
Microsoft.EntityFrameworkCore The main EF Core package that is independent of specific database providers
Microsoft.EntityFrameworkCore.SqlServer Database provider for Microsoft SQL Server and SQL Azure
Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite SQL Server support for spatial types
Microsoft.EntityFrameworkCore.Sqlite Database provider for SQLite that includes the native binary for the database engine
Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite SQLite support for spatial types
Microsoft.EntityFrameworkCore.Cosmos Database provider for Azure Cosmos DB
Microsoft.EntityFrameworkCore.InMemory The in-memory database provider
Microsoft.EntityFrameworkCore.Tools EF Core PowerShell commands for the Visual Studio Package Manager Console; use this to integrate tools like scaffolding and migrations with Visual Studio
Microsoft.EntityFrameworkCore.Design Shared design-time components for EF Core tools
Microsoft.EntityFrameworkCore.Proxies Lazy-loading and change-tracking proxies
Microsoft.EntityFrameworkCore.Abstractions Decoupled EF Core abstractions; use this for features like extended data annotations defined by EF Core
Microsoft.EntityFrameworkCore.Relational Shared EF Core components for relational database providers
Microsoft.EntityFrameworkCore.Analyzers C# analyzers for EF Core

Installing the EF Core Command Line Interface (CLI)

EF Core 3.0 및 3.1과 마찬가지로 EF Core 5.0 CLI는 더 이상 .NET Core SDK에 포함되지 않습니다. EF Core 마이그레이션 또는 스캐폴딩 명령을 실행하기 전에 이 패키지를 전역 또는 로컬 도구로 설치해야합니다.

 

처음으로 5.0 도구를 전역으로 설치하려면 다음을 사용하십시오.

dotnet tool install --global dotnet-ef --version 5.0.0

도구가 이미 설치되어있는 경우 다음으로 업데이트하십시오.

dotnet tool update --global dotnet-ef --version 5.0.0

 

반응형

'Entity Framework Core' 카테고리의 다른 글

SQL Sever Express vs SQLite  (0) 2020.12.27
Entity Framework Core 시작(2/5)  (2) 2020.12.19
Entity Framework Core 시작(1/5)  (0) 2020.12.16
Entity Framework Core 링크 정리  (0) 2020.12.14
Blazor?  (0) 2019.06.20
댓글