3

モデルを作成するときに、リレーションシップのデフォルト値を処理するための最良の方法は何でしょうか。(具体的にはEF4)

たとえば、私の組織にはデフォルトの連絡先があり、どちらが最善のアプローチであるか疑問に思いました。私はこれらの2つのオプションを手に入れました(または他の誰かがより良い場合は提案します)

関係の使用:

public  class Contact
{
    public int Id { get; set; }
    public string FirstName { get; set; }
}

public  class Organization
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Contact> Contacts { get; set; }
    //Use a relationship for the default contact?
    public Contact DefaultContact { get; set; }
}

値の使用:

public  class Contact
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    //Use value?
    public boolean IsDefault { get; set; }
}

public  class Organization
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Contact> Contacts { get; set; }
}
4

1 に答える 1

2

オプション1を使用します。2は間違いなく実装が簡単ですが、「デフォルトの連絡先を2つにすることはできません」などのルールは適用されません。私は次のようなものになります:

public class Organization {
    // ...
    public virtual ICollection<Contact> { get;set; }
    [ForeignKey("DefaultContactId")]
    public Contact DefaultContact { get;set; }
    public int? DefaultContactId { get;set; }
}

このアプローチには制限があります。ネストされた削除は機能しません(詳細については、この質問を参照してください)。このため、1対多の関係ではCascadeOnDeleteを無効にする必要があります。

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Contact>().HasRequired(co => co.Organization).WithMany().WillCascadeOnDelete(false);
}

(コードはテストなしで実行されますが、機能するはずです)

これに関するもう1つの問題は、EFがステートメントの正しい順序を把握できないため、組織を追加すると同時にデフォルトの連絡先を追加できないことです。それぞれの間で.SaveChangesを呼び出す必要があります。TransactionScopeを使用してこれを克服することはできますが、クリーンではありません。

using (var ts = new TransactionScope()) 
{
    Organization org = new Organization
    {
        // ...
        Contacts = new Collection<Contact>()
    }
    org.Contacts = new Contact() {};

    orgRepo.SaveChanges();

    // Now wire up the default contact
    org.DefaultContact = org.Contacts.First();
    orgRepo.SaveChanges();
}
于 2012-07-31T16:35:22.653 に答える