1

コードファーストであるEF6を含む他の人のコードをリファクタリングしています。データベース列を再利用して複数の外部キー関係に関与させようとしています。エンティティフレームワーク:外部キーの再利用

これを行うことで、私はスキーマを非正規化していますが、そうすることで元の設計では欠落していたモデル間でより直接的な関係を作ることができます。影響を受ける手書きのsprocsとUDFが存在するため、基礎となるデータベーススキーマの変更を最小限に抑えてこれを実現したいと思います。

FrameFrameTypeMouldingから構成されている:

モデルは、以下の業務の現在の状態を表します。 FrameTypeまたはMouldingのペアが繰り返されないので、フレームはFrameType_IdおよびMoulding_Idを超える複合主キーを持ちます。

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

    [ForeignKey("Moulding")] 
    public int Moulding_Id { get; set; } 
    public Moulding Moulding { get; set; } 

    [ForeignKey("FrameType")] 
    public int FrameType_Id { get; set; } 
    public FrameType FrameType { get; set; } 
} 

しかし、批判的に、しません:我々は他の場所で私たちはFrameTypeMouldingの両方を参照するProductを持っFrameTypeMoulding

public class FrameType 
{ 
    public int Id{get; set;} 
    public ICollection<Frame> Frames{get; set;} 
} 

public class Moulding 
{ 
    public int Id{get; set;} 
    public ICollection<Frame> Frames{get; set;} 
} 

のための最小限の実装を想定することができ

public class Frame 
{ 
    [Key,Column(Order = 0)] 
    [ForeignKey("Moulding")] 
    public int Moulding_Id { get; set; } 
    public Moulding Moulding { get; set; } 

    [Key, Column(Order = 1)] 
    [ForeignKey("FrameType")] 
    public int FrameType_Id { get; set; } 
    public FrameType FrameType { get; set; } 
} 

Frameを直接参照してください。

私はFrameにプロパティを追加したいと思います:

public ICollection<Product> Products{get; set;} 

Product上:

MouldingFrameTypeへの外部キーとしてだけではなく Moulding_IdFrameType_Idフィールドを再使用して
public Frame Frame{get; set;} 

が、 Frameへの複合外部キーとしても使用できます。

EFでこのような外部キーの「再利用」が可能ですか?

答えて

2

はい、可能です。唯一のEF6要件は、(1)参照されるエンティティプロパティがPKであること、(2)FKの部分を再利用する場合にFKプロパティがと明示的にと定義されていること。プロパティを1つの同じ名前に変更します。幸いなことに、サンプルモデルは両方の条件を満たすことができます。

私は個人的には流暢な構成を選んでいます。なぜなら、より明示的でIMOの方が簡単だからです。または、データ注釈を使用する場合は、ナビゲーションプロパティForeignKey属性で逆ではなく属性で飾ります。ボットは1つのFKフィールドをマッピングできますが、前者は複合FKフィールドをデータアニメーションにマップする唯一の方法です。あなたのサンプルモデルに適用

は次のようになります。

public class Frame 
{ 
    [Key, Column(Order = 0)] 
    public int Moulding_Id { get; set; } 

    [Key, Column(Order = 1)] 
    public int FrameType_Id { get; set; } 

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

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

    public ICollection<Product> Products { get; set; } 
} 

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

    public int Moulding_Id { get; set; } 

    public int FrameType_Id { get; set; } 

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

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

    [ForeignKey("Moulding_Id,FrameType_Id")] 
    public Frame Frame { get; set; } 
} 

しかし、小さな問題があります - 上記複数のカスケードパスを導入し、通常はオフのカスケード削除を回すためにあなたを必要とします。今度は流暢な設定を必要とし、あなたが流暢な構成を使用すると、ForeignKeyデータ注釈の必要はありませんので、Product.Frameプロパティからそれを削除し、次のように使用します。

modelBuilder.Entity<Product>() 
    .HasRequired(e => e.Frame) 
    .WithMany(e => e.Products) 
    .HasForeignKey(e => new { e.Moulding_Id, e.FrameType_Id }) 
    .WillCascadeOnDelete(false); 
+1

ワンダフル。分かりやすいここに遅れているので、AMまでこれを調べる機会はありません。私はどのように乗っているかを教えてあげます。ありがとう。 – spender

+1

治療を受けました。カスケード削除はグローバルにオフになっているので、属性設定に固執することができました。 '[foreignKey]'を 'id'プロパティからナビゲーションプロパティに移すことは、必要な洞察でした。ご協力いただきありがとうございます。 – spender

関連する問題