Нет никакого хорошего способа сделать это. Кажется, что нет простого способа вставить любой код в этот процесс после создания объекта сущности, но до того, как он будет указан в вызывающем коде.
Subclassing InternalDbSet было чем-то, что я рассматривал, но вы можете исправлять вызовы методов .Find, а реализация IQueryable (основной способ использования DbSet) недоступен.
Таким образом, единственная опция, которую я вижу слева, - не разрешать доступ к DbSet вообще, но иметь функции доступа, которые будут устанавливать свойство .Owner (или что бы вы хотели назвать) для меня. Это бесполезно, поскольку обычно вам нужно написать функцию для каждого типа запроса, который вы хотите создать, и вызывающий не мог больше использовать LINQ. Но мы можем использовать дженерики и обратные вызовы, чтобы сохранить большую часть гибкости, хотя она выглядит уродливой. Вот что я придумал.
Я работаю над портированием и очисткой сложной системы, поэтому я не в состоянии действительно проверить это, но концепция звучит. Коду может потребоваться дополнительная настройка для работы по желанию. У этого не должно быть никаких санкций, например, вытаскивая всю таблицу перед обработкой любых записей, если вы используете EnumerateEntities для перечисления вместо QueryEntities, но снова мне еще предстоит провести какое-либо реальное тестирование.
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