まず、少し背景。ASP.NET WebAPIとEntityFramework5を使用してRESTAPIを開発していますが、システムの要件は、ApiControllerとDbContextの間にロジックのいくつかのレイヤーが存在することです。これらのロジックのレイヤーには、エンティティをDbContextから切り離し、メモリ内のエンティティに仮想的な変更のセットを適用し(変更セットのマテリアライゼーションと呼んでいるプロセス)、これらの変更が発生した場合にユーザーがシステムの新しい状態を検査できるようにすることが含まれます。適用。エンティティの新しい状態は、データベースにすぐには保存されません。代わりに、マテリアライゼーションはWebサーバーのメモリに保持され、ユーザーは現在のデータまたはさまざまな変更セットの多くのマテリアライゼーションの1つを検査できます。
今私の問題のために。
public interface IIdentifiable
{
long Id { get; set; }
}
public class Foo : IIdentifiable
{
public long Id { get; set; }
public string Name { get; set; }
public List<Bar> Bars { get; set; } // Navigation Property
}
public class Bar : IIdentifiable
{
public long Id { get; set; }
public string Name { get; set; }
public long FooId { get; set; } // Foreign Key Property
public Foo Foo { get; set; } // Navigation Property
}
public class Materialization
{
IEnumerable<Foo> Foos { get; set; }
IEnumerable<Bar> Bars { get; set; }
}
public interface IRepository<TItem> : IQueryable<TItem>, ICollection<TItem>, IDisposable
where TItem : class, IIdentifiable
{
IRepository<TItem> Include<TProperty>(Expression<Func<TItem, TProperty>> path);
// Other methods
}
public class MateriailizationRepository<TItem> : IRepository<TItem>
where TItem : class, IIdentifiable
{
private Materialization _materialization;
public MateriailizationRepository(Materialization materialization)
{
_materialization = materialization;
}
public IRepository<TItem> Include<TProperty>(Expression<Func<TItem, TProperty>> path)
{
// Populate navigation property indicated by "path"
}
// Other methods
}
Foo
各バーには、それが属することを示す外部キープロパティがありますが、マテリアライゼーションプロセスが複雑になるためBar.Foo
、Foo.Bars
ナビゲーションプロパティにはデータが入力されません。したがって、マテリアライズが完了した後、Materialization.Foos
外部Materialization.Bars
キープロパティによって相互に参照するが、ナビゲーションプロパティによっては参照しないオブジェクトのコレクションが含まれます(つまり、すべてのナビゲーションプロパティの値がnullまたは空になりますList<T>
)。で次のようなことができるようになりたいですApiController
。
public IQueryable<Foo> Get (bool includeBars = false)
{
Materialization materialization;
// Materialize
using (IRepository<Foo> repository = new MateriailizationRepository<Foo>(materialization))
{
IRepository<Foo> query = repository;
if (includeBars)
query = query.Include(f => f.Bars);
return query;
}
}
MateriailizationRepository<Foo>
の主な責任はマテリアライズドオブジェクトをフェッチすることFoo
ですが、それは全体への参照を持っているので、オンデマンドからマテリアライズドオブジェクトMaterialization
を含めることができるようにしたいと思います。Bar
Materiailization.Bars
拡張メソッドMateriailizationRepository.Include()
を模倣するためにどのように実装しますか?IQueryable.Include()