Friend
クラスを拡張する必要があります。
public class Friend
{
[Key, Column(Order = 0), ForeignKey("Contact1")]
public int ContactId1 { get; set; }
public Contact Contact1 { get; set; }
[Key, Column(Order = 1), ForeignKey("Contact2")]
public int ContactId2 { get; set; }
public Contact Contact2 { get; set; }
public DateTime DateCreated { get; set; }
}
Friends
のコレクションに属性を追加しますContact
。
[InverseProperty("Contact1")]
public ICollection<Friend> Friends { get; set; }
(注釈の代わりに Fluent API を使用することもできます。)
その結果、2 つの 1 対多の関係になります (このモデルを多対多としてマップすることはできません)。1 つ目は と の間Contact.Friends
でFriend.Contact1
、2 つ目はFriend.Contact2
1 つのエンドポイントです。のエンドポイントFriend
はモデルで公開されていません。
たとえば、今日より前に作成された特定の連絡先のすべての友人の連絡先を照会できます。
DateTime today = DateTime.Now.Date;
IEnumerable<Contact> friendContacts = context.Contacts
.Where(c => c.ContactId == givenId)
.Select(c => c.Friends
.Where(f => f.DateCreated < today)
.Select(f => f.Contact2))
.SingleOrDefault();
エイト
Friend
に 2 つの必要な関係があるため、上記のマッピングは機能しませんContact
。必要な 1 対多のリレーションシップの既定では、EF はカスケード削除を有効にしますが、これは同時に 2 つのリレーションシップに対して許可されていません。カスケード削除を無効にするには、Fluent API でマッピングを書き直す必要があります。これは、データ注釈では不可能なためです。
public class Contact
{
public int ContactID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
public ICollection<Friend> Friends { get; set; }
}
public class Friend
{
public int ContactID1 { get; set; }
public Contact Contact1 { get; set; }
public int ContactID2 { get; set; }
public Contact Contact2 { get; set; }
public DateTime DateCreated { get; set; }
}
次に、派生コンテキストでオーバーライドOnModelCreating
します。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Friend>()
.HasKey(f => new { f.ContactID1, f.ContactID2 });
modelBuilder.Entity<Friend>()
.HasRequired(f => f.Contact1)
.WithMany(c => c.Friends)
.HasForeignKey(f => f.ContactID1);
modelBuilder.Entity<Friend>()
.HasRequired(f => f.Contact2)
.WithMany()
.HasForeignKey(f => f.ContactID2)
.WillCascadeOnDelete(false); // <- Important
}