MVC3에서 Code First Entity Framework (4.1)를 사용하여 외래 키 관계를 어떻게 선언해야합니까?


104

나는 많은 운없이 코드 우선 EF 4.1을 사용하여 외래 키 관계 및 기타 제약 조건을 선언하는 방법에 대한 리소스를 찾고 있습니다. 기본적으로 코드로 데이터 모델을 만들고 MVC3를 사용하여 해당 모델을 쿼리합니다. 모든 것이 훌륭한 MVC를 통해 작동하지만 (Microsoft에 대한 쿠도스!) 데이터 모델 제약이 필요하기 때문에 작동하지 않기를 원합니다.

예를 들어, 외부 개체 (테이블) 인 속성이 많은 Order 개체가 있습니다. 지금은 주문을 만들 수 있지만 외래 키 또는 외부 개체를 추가 할 수 없습니다. MVC3는 이것을 문제없이 설정합니다.

저장하기 전에 컨트롤러 클래스에 직접 개체를 추가 할 수 있다는 것을 알고 있지만 제약 조건 관계가 충족되지 않으면 DbContext.SaveChanges () 호출이 실패하고 싶습니다.

새로운 정보

따라서 특히 고객 개체를 지정하지 않고 Order 개체를 저장하려고 할 때 예외가 발생하고 싶습니다. 대부분의 Code First EF 문서에 설명 된대로 개체를 구성하는 경우에는 이것이 동작이 아닌 것 같습니다.

최신 코드 :

public class Order
{
    public int Id { get; set; }

    [ForeignKey( "Parent" )]
    public Patient Patient { get; set; }

    [ForeignKey("CertificationPeriod")]
    public CertificationPeriod CertificationPeriod { get; set; }

    [ForeignKey("Agency")]
    public Agency Agency { get; set; }

    [ForeignKey("Diagnosis")]
    public Diagnosis PrimaryDiagnosis { get; set; }

    [ForeignKey("OrderApprovalStatus")]
    public OrderApprovalStatus ApprovalStatus { get; set; }

    [ForeignKey("User")]
    public User User { get; set; }

    [ForeignKey("User")]
    public User Submitter { get; set; }

    public DateTime ApprovalDate { get; set; }
    public DateTime SubmittedDate { get; set; }
    public Boolean IsDeprecated { get; set; }
}

이것은 환자에 대한 VS 생성보기에 액세스 할 때 발생하는 오류입니다.

에러 메시지

'PhysicianPortal.Models.Order'유형의 'Patient'속성에 대한 ForeignKeyAttribute가 유효하지 않습니다. 종속 유형 'PhysicianPortal.Models.Order'에서 외래 키 이름 'Parent'를 찾을 수 없습니다. 이름 값은 쉼표로 구분 된 외래 키 속성 이름 목록이어야합니다.

문안 인사,

귀도

답변:


164

당신이있는 경우 Order클래스, 속성을 추가 참조 모델의 또 다른 클래스는, 예를 들어 것을 CustomerEF는 관계가 거기에있다 알려 충분해야한다 :

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    public virtual Customer Customer { get; set; }
}

FK관계 는 항상 명시 적으로 설정할 수 있습니다 .

public class Order
{
    public int ID { get; set; }

    // Some other properties

    // Foreign key to customer
    [ForeignKey("Customer")]
    public string CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
}

ForeignKeyAttribute생성자는 매개 변수로 문자열을 사용합니다 : 당신이 외래 키 특성에 배치하는 경우는 관련 탐색 속성의 이름을 나타냅니다. 탐색 속성에 배치하면 연결된 외래 키의 이름을 나타냅니다.

이것이 의미하는 바는 속성 ForeignKeyAttribute에 를 배치 할 Customer경우 속성이 CustomerID생성자에서 가져 옵니다.

public string CustomerID { get; set; }
[ForeignKey("CustomerID")]
public virtual Customer Customer { get; set; }

최신 코드를 기반으로 편집 다음 줄 때문에 오류가 발생합니다.

[ForeignKey("Parent")]
public Patient Patient { get; set; }

EF는 Parent외래 키 시행자로 사용하기 위해 호출 된 속성을 찾습니다 . 다음 두 가지 작업을 수행 할 수 있습니다.

1) 제거하고 필요에 따라 관계를 표시하기 위해로 ForeignKeyAttribute교체하십시오 RequiredAttribute.

[Required]
public virtual Patient Patient { get; set; }

로 속성을 장식하는 RequiredAttribute것도 좋은 부작용이 ON DELETE CASCADE있습니다. 데이터베이스의 관계는 .

또한 virtualLazy Loading을 사용 하도록 속성 을 만드는 것이 좋습니다 .

2) Parent외래 키로 사용할 속성을 만듭니다 . 이 경우 예를 들어 호출하는 것이 더 합리적 일 것입니다 ParentID(이름도 변경해야합니다 ForeignKeyAttribute).

public int ParentID { get; set; }

이 경우 내 경험 상으로는 다른 방법으로 사용하는 것이 더 좋습니다.

[ForeignKey("Patient")]
public int ParentID { get; set; }

public virtual Patient Patient { get; set; }

감사합니다 Sergi-블록 따옴표에 몇 가지 추가 정보를 추가했습니다.
Guido Anselmi 2011

@Guido-최신 코드 편집을 기반으로 답변을 업데이트했습니다. 도움이 되었기를 바랍니다.
Sergi Papaseit 2011

30

다음과 같이 외래 키를 정의 할 수 있습니다.

public class Parent
{
   public int Id { get; set; }
   public virtual ICollection<Child> Childs { get; set; }
}

public class Child
{
   public int Id { get; set; }
   // This will be recognized as FK by NavigationPropertyNameForeignKeyDiscoveryConvention
   public int ParentId { get; set; } 
   public virtual Parent Parent { get; set; }
}

이제 ParentId는 외래 ​​키 속성이며 자식과 기존 부모 사이에 필요한 관계를 정의합니다. 기존 부모없이 자식을 저장하면 예외가 발생합니다.

FK 속성 이름이 탐색 속성 이름과 상위 PK 이름으로 구성되지 않은 경우 ForeignKeyAttribute 데이터 주석 또는 Fluent API를 사용하여 관계를 매핑해야합니다.

데이터 주석 :

// The name of related navigation property
[ForeignKey("Parent")]
public int ParentId { get; set; }

Fluent API :

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

다른 유형의 제약 조건은 데이터 주석 및 모델 유효성 검사를 통해 적용 할 수 있습니다 .

편집하다:

을 설정하지 않으면 예외가 발생합니다 ParentId. 필수 속성입니다 (null 허용 아님). 설정하지 않으면 아마도 데이터베이스에 기본값을 보내려고 할 것입니다. 기본값은 0이므로 Id = 0 인 고객이없는 경우 예외가 발생합니다.


감사합니다 Ladislav-블록 따옴표에 몇 가지 추가 정보를 추가했습니다.
Guido Anselmi 2011

@Ladislav. 따라서이 제약 조건을 적용하려면 Parent에 대한 참조와 ParentId에 대한 참조가 모두 있어야합니다. 그 맞습니까? 참고로 위의 실제 클래스를 추가하겠습니다.
Guido Anselmi 2011

@Guido : 그것이 새로운 정보입니다. 외래 키 속성을 사용하고 있지 않습니다. 모든 탐색 속성은 기본적으로 선택 사항으로 처리됩니다. 유창한 매핑을 사용하여 필요에 따라 매핑하십시오.
Ladislav Mrnka 2011

@Ladislav : 다시 한 번 감사합니다. 데이터 주석과 Fluent API 사용의 차이점을 이해하기 위해 주변을 둘러보고 있습니다. 나는 당신이 말하고 있다고 생각하는 것에 따라 위의 코드를 변경했습니다. 내가해야 할 일은 무엇입니까? 문안 인사.
Guido Anselmi 2011

ForeignKey 속성은 외래 키 속성과 관련된 탐색 속성을 정의하지 않으며 그 반대의 경우도 마찬가지입니다. 외래 키 속성이 없으므로 해당 속성을 사용할 수 없습니다. 탐색 속성에서 필수 속성을 사용해보십시오 (테스트하지 않았습니다).
Ladislav Mrnka 2011
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.