web-dev-qa-db-ja.com

MVC3でCode First Entity Framework(4.1)を使用して外部キー関係を宣言する方法

コードを最初に使用して外部キー関係やその他の制約を宣言する方法に関するリソースを探していますEF 4.1。基本的に、コードでデータモデルを構築し、MVC3を使用してそのモデルを照会しています。すべてがMVCを介して機能しますが(これはMicrosoftにとっては素晴らしいことですが)、データモデルの制約が必要なため、機能しません。

たとえば、外部オブジェクト(テーブル)である大量のプロパティを持つOrderオブジェクトがあります。今は問題なく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は無効です。外部キー名「Parent」が依存型「PhysicianPortal.Models.Order」で見つかりませんでした。 Name値は、外部キープロパティ名のコンマ区切りリストである必要があります。

よろしく、

グイド

95
Guido Anselmi

Orderクラスがある場合、モデル内の別のクラスを参照するプロパティを追加すると、たとえばCustomerはEFに関係があることを知らせるのに十分なはずです。

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コンストラクターはパラメーターとして文字列を取ります。外部キープロパティに配置すると、関連付けられたナビゲーションプロパティの名前を表します。ナビゲーションプロパティに配置すると、関連付けられた外部キーの名前を表します。

つまり、ForeignKeyAttributeCustomerプロパティに配置する場合、属性はコンストラクターでCustomerIDを取ります。

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

最新のコードに基づいた編集この行のためにエラーが発生します:

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

EFはParentというプロパティを探し、それを外部キーエンフォーサとして使用します。次の2つのことができます。

1)ForeignKeyAttributeを削除し、RequiredAttributeに置き換えて、必要に応じて関係をマークします。

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

プロパティをRequiredAttributeで装飾することには、ニースの副作用もあります。データベース内の関係は、ON DELETE CASCADEで作成されます。

また、プロパティvirtualを作成して、遅延読み込みを有効にすることをお勧めします。

2)外部キーとして機能するParentというプロパティを作成します。その場合は、おそらくParentID(たとえば、ForeignKeyAttributeの名前も変更する必要があります)を呼び出す方が意味があります。

public int ParentID { get; set; }

この場合の私の経験では、他の方法でそれを持っている方が良いです:

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

public virtual Patient Patient { get; set; }
154
Sergi Papaseit

次の方法で外部キーを定義できます。

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の顧客がいない場合は例外が発生します。

29
Ladislav Mrnka