Entity Frameworkにオブジェクトが存在するかどうかを確認する最良の方法?
DbSet
内のエンティティをチェックする一般的な方法を探しています。機能しないこのようなもの:
private DbContext DbContext { get; set; }
private DbSet<T> DbSet { get; set; }
public Boolean Exists(T entity) {
return ((from item in this.DbSet
where item == entity
select item).Count() > 0);
}
この線 where item == entity
はLINQ to SQLで機能しますが、明らかにLINQ to Entitiesでは機能しません。エンティティは異なるキーを持っている可能性があるため、既知のキーを持つ共通の抽象からすべてを比較のために継承させることはできません。
これはできますが、検証プロセスとして例外をキャッチするパフォーマンスが心配です エンティティが切り離されている限りOriginalValues
プロパティを取得できないため、これも機能しません。
public Boolean Exists(T entity) {
try {
var current = this.DbContext.Entry(entity).OriginalValues;
// Won't reach this line if the entity isn't in the database yet
return true;
}
catch (Exception ex) {
return false;
}
}
エンティティがコンテキストによってロードされたかどうかを確認する一般的な方法、またはエンティティが存在する場合にデータベースを照会する一般的な方法が必要ですか?
前者の場合:
public bool Exists<T>(T entity) where T: class
{
return this.Set<T>().Local.Any(e => e == entity);
}
後者の場合に使用します(読み込まれたエンティティもチェックします):
public bool Exists<T>(params object[] keys)
{
return (this.Set<T>().Find(keys) != null);
}
編集:
EFコードは最初にこの種の情報にアクセスすることを想定していませんが、エンティティキーの名前を取得することは可能です。私はそのような何かがうまくいくと思う:
var objContext = ((IObjectContextAdapter)dbContext).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var keyNames = objSet.EntitySet.ElementType.KeyMembers.Select(m => m.Name);
しかし、これはすべて意味がありません。ジェネリックアプローチが必要ですが、エンティティはジェネリックアプローチを可能にするために必要な情報を共有しません。今、あなたはキー値さえ知らないと言います。この「汎用」アプローチを使用するには、リフレクションと式ツリーの手動構築が必要です。
私を正しい方向に導いてくれた@Ladislavに感謝します。汎用Exists()
メソッドのコードは次のとおりです。
これはリフレクションを必要とせず、非常によく機能するように見えることに注意してください。ワクワクしていない唯一のことは、TryGetObjectByKey()
には見つかったエンティティをアタッチする副作用があるということです。 Exists()
に意図しない結果を与えたくないので、エンティティが見つかった場合は切り離す必要があります。
public Boolean Exists(T entity) {
var objContext = ((IObjectContextAdapter)this.DbContext).ObjectContext;
var objSet = objContext.CreateObjectSet<T>();
var entityKey = objContext.CreateEntityKey(objSet.EntitySet.Name, entity);
Object foundEntity;
var exists = objContext.TryGetObjectByKey(entityKey, out foundEntity);
// TryGetObjectByKey attaches a found entity
// Detach it here to prevent side-effects
if (exists) {
objContext.Detach(foundEntity);
}
return (exists);
}