いくつかの依存関係を逆転させるために、アプリケーションをリファクタリングしています。元のコードの一部は、DbContext.Set<MyEntityType>()
クエリ対象のセットを取得するために使用します。
反転により、 MyEntityType はコードを使用して明示的に認識されなくなったDbContext.Set<MyEntityType>()
ため、代わりに使用していDbContext.Set(TypeVariable)
ます。
リファクタリングは、正しい DbSet が返される範囲で機能します。
ただし、タイプDbContext.Set(TypeVariable).Local
はIList
(含まれるタイプは不明) であるのに対し、 のタイプはDbContext.Set<MyEntityType>().Local
でしたObservableCollection<MyEntityType>
。これは、DbSet に対して Linq を実行することが不可能になったことを意味します。
私が達成できた最善の回避策は、MyEntityType およびその他のエンティティ タイプが実装するインターフェイスにキャストすることです (明確にするために一部のコードは省略されています)。
var set = Context.Set(targetType);
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
var querables = set as IQueryable<IActionTarget>;
entity = querables.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
だから、2つの質問:
DbContext.Set(TypeVariable)
強く型付けされたセットを返さないのはなぜですか?
依存関係の逆転を行うより良い方法はありますか?
要求されたいくつかの詳細
依存関係がすべてです。Model には、通常の方法で EF Code First を介して (ただし、Repositoryを介して) 永続化される POCO クラスが含まれています。ActionEvaluatorは受信データを受け取り、Repository メソッドを介して、実行する必要があるアクションを決定します。つまり、DbSet に対するクエリです。
元のコードでは、1 種類の受信データ (特定の形式の CSV) しかなく、ActionEvaluator はこのデータに密接に依存しており、どの POCO クラスがどの CSV レコードに適用できるかを認識していました。
ここで、さまざまな CSV 形式と Web API メッセージを使用するように拡張したいと考えています。これを行うには、依存関係を反転して、DataSourceが ActionEvaluator にレコードが適用される POCO クラスを伝える必要があります。これは Type 変数によって行われます。
そのため、ActionEvaluator はジェネリック型パラメーターを使用できなくなりましたが、型変数をリポジトリに渡して、正しい DbSet を見つけることができます。
DbContext.Set<AnEntity>()
問題は、DbSetを見つける 2 つの方法の違いDbContext.Set(TypeVariable)
です。
これら2つの戻り値を機能的に同等にするためにEFの機能強化を求めていると思いますが、2番目のバージョンの型は実行時に決定されるため、それは不可能かもしれません。
要求された完全なメソッド コードは次のとおりです。
private IActionTarget DbContextGetEntity(Type targetType, IActionTarget key)
{
var set = Context.Set(targetType);
if (set == null)
{
throw new Exception("Unable to find DbSet for type '{0}'".F(targetType.Name));
}
// Look in the local cache first
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
if (entity == null)
{
// If not found locally, hit the database
var querables = set as IQueryable<IActionTarget>;
if (querables != null)
{
entity = querables.FirstOrDefault(e => e.Id == key.Id && e.EffectiveDate == key.EffectiveDate);
}
}
return entity;
}
理想的には交換したい
var entity = set.Local.OfType<IActionTarget>()
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);
と
var entity = set.Local.OfType(targetType)
.FirstOrDefault(l => l.Id == key.Id && l.EffectiveDate == key.EffectiveDate);