2012-04-16 28 views
0

エンティティフレームワークの外部キーの関係に問題があります。私は2つのテーブル:PersonsCountriesを持っています。 Personsには、CountryIdへの外部キー列があります。Entity Frameworkの外部キーが正しく更新されない

Countriesテーブルがめったに変更されないため、データを一度だけ取り込み、DatabaseContextを処分し、Countriesのリストをどこかにキャッシュしておきます。これが私が問題に取り組んでいるところです。

エンティティフレームワークでは、データベースコンテキストを開いたり、必要に応じて行を追加/編集したり、データベースコンテキストを閉じたりする必要があるようです。オープンすると、データをフェッチして閉じます。後で開いて、データを保存し、閉じる。それは問題がある。

だから私のPOCOオブジェクトは次のようになります。そして、

public class Country { 
    public int CountryId {get; set; } 
    public String Name {get; set; } 
} 

public Person { 
    public int PersonId {get; set; } 
    public virtual Country Country {get; set; } 
} 

、私はこのような新しい人を作成してみてください:保存を

Country[] countries; 
using (var dt = new DatabaseContext()) 
{ 
    countries= dt.Countries.ToArray(); 
} 

Person person = new Person(); 
person.Country = countries[0]; 
using (var dt = new DatabaseContext()) { 
    dt.Entities.Add(person); 
    dt.SaveChanges(); 
} 

を、エンティティフレームワークは、新しい行を作成しますCountriesテーブルは、countries[0]と同じ名前ですが、新しい増分IDです。これは明らかに望ましい結果ではありません。ユーザーはCountry_CountryIdフィールドのIDをcountries[0]に設定し、新しい行を作成すべきではありません。

どうすれば解決できますか? 1つの解決策は、エンティティフレームワークを強制的ににすることではないと思います。すでに主キーが設定されているオブジェクトが指定されたときに新しい行を作成します。これを行う方法はありますか?

答えて

3

これは、非常に一般的な問題が数日おきに尋ねられるので、問題を説明するためにかなり大きな努力を払う前に、少なくともインターネット上で少しずつ検索しているのだろうかと思います。

Addメソッドは、エンティティグラフ内のすべてのエンティティを追加します。したがって、〜personcountryを現在のコンテキストに添付していない場合は、personAddを呼び出すと、新しいエンティティとしてpersoncountryの両方が挿入されます。

Person person = new Person(); 
person.Country = countries[0]; 
using (var dt = new DatabaseContext()) { 
    dt.Entities.Add(person); 
    dt.Entry(person.Country).State = EntityState.Modified; 
    dt.SaveChanges(); 
} 
+1

あなたの答えをありがとうが、このソリューションは理想的ではありません。なぜならプログラマが各エンティティに対して 'EntityState.Modified'を設定する必要があるからです。これが問題につながり、カプセル化を破るように感じます。それは、それがuntrackedオブジェクトを添付する時点で 'Add'をインターセプトする方法はありますか? – Oliver

+0

これを行うには、この解決策が正しいと思われます。エンティティグラフをEFがロードしないで永続させるため、EFにリレーションシップの変更を伝える必要があります。 'Add'メソッドはインターセプトできません。それは仮想ではないので、上書きすることさえできません。 –

+0

私はこれがかなり大きな問題だと思っています。あなたのソリューションは、実際のデータベースにはうまくいかないでしょう。ここで、 'Person'は5つの異なる国への参照、いくつかの型、関係の定義などを保持しています。これらすべてのために 'EntityState.Modified'を書くには多くのコード行が必要となり、維持管理が悪いでしょう。しかし、私はより良い解決策を考えることができません。 – Oliver

1

私は私のDatabaseContextクラスに次の2つのメソッドを追加することによってこの問題を解決しています:

public void Add(object target) 
{ 
    this.Set(target.GetType()).Attach(target); 
    this.Entry(target).State = System.Data.EntityState.Added; 
} 

public void Modify(object target) 
{ 
    this.Set(target.GetType()).Attach(target); 
    this.Entry(target).State = System.Data.EntityState.Modified; 
} 
あなたは countryを挿入したくない場合は、 countryが新しいエンティティではないことをEFを伝える必要があります
+0

これはとても混乱しています。何らかの理由で、 'Add'メソッドが動作していますが、' Modify'メソッドは動作していません。 – Oliver

関連する問題