IT Share you

탐색 속성이없는 EF 코드 첫 번째 외래 키

shareyou 2020. 12. 10. 21:29
반응형

탐색 속성이없는 EF 코드 첫 번째 외래 키


다음 엔티티가 있다고 가정 해 봅시다.

public class Parent
{
    public int Id { get; set; }
}
public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }
}

탐색 속성을 가질 필요없이 Parents 테이블에 대한 외래 키 제약 조건을 사용하여 ParentId가 데이터베이스에 생성되도록하는 코드 첫 번째 유창한 API 구문은 무엇입니까 ?

탐색 속성 Parent를 Child에 추가하면 다음과 같이 할 수 있습니다.

modelBuilder.Entity<Child>()
    .HasRequired<Parent>(c => c.Parent)
    .WithMany()
    .HasForeignKey(c => c.ParentId);

하지만이 특별한 경우에는 탐색 속성을 원하지 않습니다.


EF Code First Fluent API로는 불가능합니다. 데이터베이스에서 외래 키 제약 조건을 만들려면 항상 하나 이상의 탐색 속성이 필요합니다.

Code First 마이그레이션을 사용하는 경우 패키지 관리자 콘솔 ( add-migration SomeNewSchemaName) 에서 새 코드 기반 마이그레이션을 추가하는 옵션이 있습니다 . 모델 또는 매핑으로 변경 한 경우 새 마이그레이션이 추가됩니다. 아무것도 변경하지 않은 경우 add-migration -IgnoreChanges SomeNewSchemaName. 이 경우 마이그레이션에는 비어있는 UpDown메소드 만 포함됩니다 .

그런 Up다음 다음을 추가하여 메서드를 수정할 수 있습니다 .

public override void Up()
{
    // other stuff...

    AddForeignKey("ChildTableName", "ParentId", "ParentTableName", "Id",
        cascadeDelete: true); // or false
    CreateIndex("ChildTableName", "ParentId"); // if you want an index
}

이 마이그레이션을 실행하면 ( update-database패키지 관리 콘솔에서) 다음과 유사한 SQL 문이 실행됩니다 (SQL Server의 경우).

ALTER TABLE [ChildTableName] ADD CONSTRAINT [FK_SomeName]
FOREIGN KEY ([ParentId]) REFERENCES [ParentTableName] ([Id])

CREATE INDEX [IX_SomeName] ON [ChildTableName] ([ParentId])

또는 마이그레이션없이 다음을 사용하여 순수 SQL 명령을 실행할 수 있습니다.

context.Database.ExecuteSqlCommand(sql);

여기서는 context파생 된 컨텍스트 클래스의 인스턴스이며 sql위의 SQL 명령 (문자열)입니다.

이 모든 EF에는 ParentId관계를 설명하는 외래 키라는 단서가 없습니다 . EF는이를 일반 스칼라 속성으로 만 간주합니다. 어떻게 든 위의 모든 것은 SQL 관리 도구를 열고 수동으로 제약 조건을 추가하는 것에 비해 더 복잡하고 느린 방법입니다.


이 게시물에 대한하지만 Entity Framework하지 Entity Framework Core, 그것은 (나는 V1.1.2을 사용하고 있습니다) 엔티티 프레임 워크 코어를 사용하여 같은 일을 달성하기 위해 원하는 사람을 위해 유용 할 수 있습니다.

나는 (비록 그들이있는 거 좋은) 탐색 속성을하지 않아도 내가 DDD를 연습하고 내가 원하기 때문에 Parent그리고 Child두 개의 별도의 집계 뿌리가 될 수 있습니다. 인프라 별 Entity Framework탐색 속성이 아닌 외래 키를 통해 서로 대화 할 수 있기를 바랍니다 .

당신이해야 할 모든 이용하여 한쪽의 관계를 구성하는 것입니다 HasOne하고 WithMany(그들은 결국이 아니에요) 탐색 속성을 지정하지 않고.

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {}

    protected override void OnModelCreating(ModelBuilder builder)
    {
        ......

        builder.Entity<Parent>(b => {
            b.HasKey(p => p.Id);
            b.ToTable("Parent");
        });

        builder.Entity<Child>(b => {
            b.HasKey(c => c.Id);
            b.Property(c => c.ParentId).IsRequired();

            // Without referencing navigation properties (they're not there anyway)
            b.HasOne<Parent>()    // <---
                .WithMany()       // <---
                .HasForeignKey(c => c.ParentId);

            // Just for comparison, with navigation properties defined,
            // (let's say you call it Parent in the Child class and Children
            // collection in Parent class), you might have to configure them 
            // like:
            // b.HasOne(c => c.Parent)
            //     .WithMany(p => p.Children)
            //     .HasForeignKey(c => c.ParentId);

            b.ToTable("Child");
        });

        ......
    }
}

엔터티 속성을 구성하는 방법에 대한 예제도 제공하지만 여기서 가장 중요한 것은 HasOne<>, WithMany()HasForeignKey()입니다.

도움이 되었기를 바랍니다.


DataAnotations를 사용하고 탐색 속성을 노출하고 싶지 않은 사람들을위한 작은 힌트-사용 protected

public class Parent
{
    public int Id { get; set; }
}
public class Child
{
    public int Id { get; set; }
    public int ParentId { get; set; }

    protected virtual Parent Parent { get; set; }
}

그것은 그게 전부 -와 외래 키 cascade:true후가 Add-Migration생성됩니다.


EF Core의 경우 탐색 속성을 제공 할 필요가 없습니다. 관계의 한쪽에 간단히 외래 키를 제공 할 수 있습니다. Fluent API를 사용한 간단한 예 :

    using Microsoft.EntityFrameworkCore;
    using System.Collections.Generic;

    namespace EFModeling.Configuring.FluentAPI.Samples.Relationships.NoNavigation
    {
        #region Model
        class MyContext : DbContext
        {
            public DbSet<Blog> Blogs { get; set; }
            public DbSet<Post> Posts { get; set; }

            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                 modelBuilder.Entity<Post>()
                    .HasOne<Blog>()
                    .WithMany()
                    .HasForeignKey(p => p.BlogId);
             }
        }

        public class Blog
        {
             public int BlogId { get; set; }
             public string Url { get; set; }
        }

        public class Post
        {
             public int PostId { get; set; }
             public string Title { get; set; }
             public string Content { get; set; }

            public int BlogId { get; set; }
        }
        #endregion
    }

참고URL : https://stackoverflow.com/questions/20886049/ef-code-first-foreign-key-without-navigation-property

반응형