5

SQL ce 4.0で最初にEF 4.1コードを使用しています

私は2つのクラスを持っています

public class Customer
{
    public int ID { get; set; }

    public string CompanyName { get; set; }

    public List<ContactPerson> ContactPersons { get; set; }
}

public class ContactPerson
{
    public int ID { get; set; }

    public string Name { get; set; }

}

および DbContext

public class MyDB : DbContext
{
    public DbSet<ContactPerson> ContactPersons { get; set; }

    public DbSet<Customer> Customers { get; set; }

    public MyDB()
    {
        this.Configuration.LazyLoadingEnabled = true;
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Customer>()
            .HasMany(c => c.ContactPersons)
            .WithRequired()
            .WillCascadeOnDelete(true);
    }
}

同時に、コード内で Customer の ContactPerson のコレクション全体を更新する必要があります。

List<ContactPersons> modifiedContactPersons;
Customer customer = MyDB.Customers.Find(ID);
customer.ContactPersons = modifiedContactPersons;

MyDB.SaveChanges() を呼び出すと、次の例外が発生します。

リレーションシップの外部キー プロパティを公開しないエンティティの保存中にエラーが発生しました。単一のエンティティを例外のソースとして識別できないため、EntityEntries プロパティは null を返します。保存中の例外の処理は、エンティティ タイプで外部キー プロパティを公開することで簡単に行うことができます。詳細については、InnerException を参照してください。

内部例外あり:

「Customer_ContactPersons」AssociationSet からの関係は「削除済み」状態です。多重度の制約がある場合、対応する「Customer_ContactPersons_Target」も「削除済み」状態でなければなりません。

これが意味することは理解できますが、自分で問題を解決することはできません。助言がありますか?

4

1 に答える 1

8

ここでの問題は次のとおりです。

customer.ContactPersons = modifiedContactPersons;

古い関連担当者のリストを新しい関連担当者のリストに置き換え、次の 2 つの操作を行います。

  • 最初に、以前に関係していたすべての人物との関係をマークします。Deleted
  • 次に、すべての新しい契約者を添付し、それらとの関係を次のようにマークします。Added

リレーションを削除しても関連するエンティティは削除されないため、最初の操作は問題です。そのため、ContactPersonどれにも関連付けられてCustomerおらず、マッピングで許可されていません (FK は null 可能ではありません)。

この問題の解決は、達成しようとしている要件によって異なります。最初にすべての関連人物を本当に削除したい場合は、新しいリストを割り当てる前に、それぞれの状態を手動で削除済みに設定する必要があります。既存の人物を更新したい場合は、これをまったく行うべきではありません。顧客に関連する人物を反復し、新しいリストからデータを変更する必要があります。なんで?なぜなら:

  • エンティティを削除して、既存のエンティティを更新する代わりに新しいエンティティを挿入すると、データベース変更ステートメントが 1 つではなく 2 つになります = データベースへのラウンドトリップが 1 つではなく 2 回になり、エンティティが多い場合は、アプリケーションが大幅に遅くなります。
  • 依存している他のエンティティがある場合、それをContractPerson削除することはできません。また、どこかでContractPerson'sを使用Idし、それが自動生成されている場合、元のレコードを削除した後は存在しなくなります。
  • それは一般的にひどく間違った怠惰なアプローチです。新しいレコードを挿入し、既存のレコードを変更し、本当に削除する必要があるレコードのみを削除します。
于 2011-07-19T09:58:46.660 に答える