これを行うには良い方法はありません。エンティティオブジェクトが構築された後、呼び出し元コードで列挙される前に、コードをプロセスに注入する簡単な方法はないようです。
Subclassing InternalDbSetは私が考えたものですが、.FindメソッドとIQueryable実装(DbSetを使用する主な方法)への呼び出しを解決することはできません。
私が左に見ることができる唯一のオプションは、DbSetへのアクセスを全く許可しないことですが、.Owner(またはあなたがそれを呼びたいもの)プロパティを設定するアクセサ関数を持っています。これは面倒です。通常は、作成するすべてのクエリタイプに対して関数を記述しなければならず、呼び出し元はLINQを使用できなくなります。しかし、醜く見えますが、ほとんどの柔軟性を維持するためにジェネリックスやコールバックを使用できます。ここに私が思いついたのがあります。
複雑なシステムの移植とクリーンアップに取り組んでいますので、まだ実際にテストする立場にはいませんが、コンセプトは健全です。コードは、必要に応じてさらに調整を行う必要があります。これは、QueryEntitiesの代わりに列挙するためにEnumerateEntitiesを使用している限り、レコードを処理する前にテーブル全体をプルダウンするなどの罰則はありませんが、もう一度これについて実際のテストをまだしていません。
private void InitEntity(Entity entity) {
if (entity == null) {
return;
}
entity.Owner = this;
// Anything you want to happen goes here!
}
private DbSet<Entity> Entities { get; set; }
public IEnumerable<Entity> EnumerateEntities() {
foreach (Entity entity in this.Entities) {
this.InitEntity(entity);
yield return entity;
}
}
public IEnumerable<Entity> EnumerateEntities(Func<DbSet<Entity>, IEnumerable<Entity>> filter) {
IEnumerable<Entity> ret = filter(this.Entities);
foreach (Entity entity in ret) {
this.InitEntity(entity);
yield return entity;
}
}
public T QueryEntities<T>(Func<DbSet<Entity>, T> filter) {
if (filter is Func<DbSet<Entity>, Entity>) {
T ret = filter(this.Entities);
this.InitEntity(ret as Entity);
return ret;
}
if (filter is Func<DbSet<Entity>, IEnumerable<Entity>>) {
IEnumerable<Entity> ret = filter(this.Entities) as IEnumerable<Entity>;
// You should be using EnumerateEntities, this will prefetch all results!!! Can't be avoided, we can't mix yield and no yield in the same function.
return (T)ret.Select(x => {
this.InitEntity(x);
return x;
});
}
return filter(this.Entities);
}
public void QueryEntities(Action<DbSet<Entity>> filter) => filter(this.Entities);
ありがとう - これは私の絶望的な検索を終わらせる – Kathleen