エンティティフレームワークの外部キーの関係に問題があります。私は2つのテーブル:Persons
とCountries
を持っています。 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つの解決策は、エンティティフレームワークを強制的ににすることではないと思います。すでに主キーが設定されているオブジェクトが指定されたときに新しい行を作成します。これを行う方法はありますか?
あなたの答えをありがとうが、このソリューションは理想的ではありません。なぜならプログラマが各エンティティに対して 'EntityState.Modified'を設定する必要があるからです。これが問題につながり、カプセル化を破るように感じます。それは、それがuntrackedオブジェクトを添付する時点で 'Add'をインターセプトする方法はありますか? – Oliver
これを行うには、この解決策が正しいと思われます。エンティティグラフをEFがロードしないで永続させるため、EFにリレーションシップの変更を伝える必要があります。 'Add'メソッドはインターセプトできません。それは仮想ではないので、上書きすることさえできません。 –
私はこれがかなり大きな問題だと思っています。あなたのソリューションは、実際のデータベースにはうまくいかないでしょう。ここで、 'Person'は5つの異なる国への参照、いくつかの型、関係の定義などを保持しています。これらすべてのために 'EntityState.Modified'を書くには多くのコード行が必要となり、維持管理が悪いでしょう。しかし、私はより良い解決策を考えることができません。 – Oliver