以下は、EF 5.0.0-rc と Code First を使用しています。私の設計では、属性エンティティがあります。
public class Attribute
{
public int AttributeId { get; set; }
public Guid Guid { get; set; }
public string Name { get; set; }
public string Value { get; set; }
/* Used for testing the first fluent statement */
public virtual ICollection<Customer> Customers { get; set; }
}
GUID を含む複数のエンティティもあります。
public class Customer
{
public int CustomerId { get; set; }
public Guid Guid { get; set; }
}
public class Location
{
public int LocationId { get; set; }
public Guid Guid { get; set; }
}
属性テーブルを顧客テーブルと場所テーブルの両方に共通にし、その間に列やテーブルを入れないようにしたいと考えています。流暢な API で正しいマッピングを取得して、ヘルパー テーブルなしで FK を作成できないようです。
modelBuilder.Entity<Customer>()
.HasMany(o => o.Attributes)
.WithMany(o => o.Customers)
.Map(m => m.MapLeftKey("Guid"));
...必要のない CustomerAttributes テーブルを生成します。
modelBuilder.Entity<Organization>()
.HasMany(o => o.Attributes)
.WithOptional()
.HasForeignKey(o => o.Guid);
...コンパイルされないため
参照制約の依存ロールのすべてのプロパティの型は、対応する主ロールのプロパティの型と同じでなければなりません。
関係はどのように設定する必要がありますか? それとも、デザインが適切ではないですか?
編集:成功!
Raphaël Althaus の指示で、私は EF のやり方に屈し、エンティティごとに個別の追跡テーブルを使用する準備ができていましたが、Cust エンティティと Loca エンティティが継承する新しいクラスを作成するという彼の提案は、私を正しい方向に導きました。
まず、「親」クラスを作成しました。これにより、ほとんどのエンティティに格納されている監査データの一部をリファクタリングする場所も提供されました。
public class ParentEntity
{
[Key]
public Guid Guid { get; set; }
public DateTime? CreatedOn { get; set; }
public string CreatedBy { get; set; }
public DateTime? ModifiedOn { get; set; }
public string ModifiedBy { get; set; }
[Timestamp]
public byte[] Version { get; set; }
public virtual ICollection<Attribute> Attributes { get; set; }
}
次に、Cust エンティティと Loca エンティティの親クラスを継承しました。
public class Customer : ParentEntity
{
public int CustomerId { get; set; }
public Guid Guid { get; set; }
}
public class Location : ParentEntity
{
public int LocationId { get; set; }
public Guid Guid { get; set; }
}
また、新しい FK フィールド EntityGuid をサポートするように Attribute クラスを変更しました。
public class Attribute
{
public int AttributeId { get; set; }
public Guid EntityGuid { get; set; }
public string Name { get; set; }
public string Value { get; set; }
}
これにより、すべてのエンティティを新しい ParentEntity テーブルに格納しようとしたことを除いて、必要なものはほとんどすべて得られました。私が使用したことを修正するには:
modelBuilder.Entity<Customer>().ToTable("Customers");
modelBuilder.Entity<Location>().ToTable("Locations");
そして最後に、すべてをまとめるピース:
modelBuilder.Entity<ParentEntity>()
.HasMany(e => e.Attributes)
.WithRequired()
.HasForeignKey(e => e.EntityGuid);
私が言える唯一の欠点は、ParentEntity が Guid である主キーとして引き継がれることです。ただし、他のキーはそのままにして、それらをクラスタリング インデックスとして使用する予定です。