Я работаю в. net core 3.0 и Entity Framework Core 5 с использованием Jetbrains Rider.
Я разрабатываю приложение, и в настоящее время я пытаюсь создать методы, чтобы сделать возможной загрузку возможной и легко сделать из уровня business-logi c, не обращаясь напрямую к нашему объекту DbContext (который доступен только как частное поле только для чтения классов репозитория).
Чтобы дать вам представление о том, что я пытаюсь чтобы сделать, это то, что я уже сделал (не имеет отношения к моему вопросу, только для контекста). Этот метод определен в классе stati c на моем уровне технических услуг, который я могу вызвать, не обращаясь непосредственно к своему объекту DbContext (я только указываю, какое навигационное свойство я хочу загрузить из базы данных в качестве параметра)
public void ReferenceNavProperty<T>(T obj, Expression<Func<T, object>> expression, bool loadAll)
where T : class
{
var reference = context.Entry(obj).Reference(expression);
if (reference != null)
context.Entry(obj).References.Append(reference);
if (loadAll)
LoadAllReferenced(obj); //<- does a .Load() on every EntryReference and CollectionEntry of the specified object
}
Поэтому, когда я получаю объект, обладающий навигационным свойством, которое я хочу загрузить, я вызываю этот метод следующим образом:
ReferenceNavProperty<Session>(session, s => s.SomeNavigationalProperty, true);
И я успешно загружаю навигационное свойство, указав только который свойство, и, следовательно, с уважением к архитектуре.
Теперь на вопрос: Я хочу сделать sh нечто подобное, для быстрой загрузки. Предыдущий пример явной загрузки был довольно простым, потому что я легко могу отделить EntryReference / EntryCollections от метода .Load (), а затем позже загрузить все эти ссылки. Однако при активной загрузке методы Include () и ThenInclude () должны быть связаны друг с другом, я попытался также разделить эти 2 (так что мне не нужно их обязательно связывать), это то, что я сначала попробовал:
// T is a generic class type variable
public IIncludableQueryable<T, object> ReadAndInclude(Expression<Func<T, object>> expression)
{
//context is a private readonly field of type DbContext
return context.Set<T>().Include(expression);
}
Этот метод будет обращаться к DbContext и включать первое свойство (выражение), но затем он будет возвращать интерфейс IIncludableQueryable, чтобы вызывающая сторона (вызывающая этот метод) могла связать несколько цепочек Include () или ThenInclude. () вызывает этот интерфейс IIncludableQueryable и, таким образом, делает доступной загрузку доступной из уровня business-logi c без прямого доступа к нашему объекту DbContext.
Это на самом деле работает. Вид ... Если я сделаю следующее:
//SessieDeelnames and Klas are just 2 navigational properties of session
sessieRepo.ReadAndInclude(session => session.SessieDeelnames).Include(session => session.Klas);
Когда я вызываю .Include () (чтобы включить второй дочерний элемент для свойства 'Klas'), тогда это работает. но когда я пытаюсь сделать это с помощью .ThenInclude (поскольку ReadAndInclude уже включает свойство, я должен иметь возможность связать вызов ThenInclude), он не распознает свойство источника:
sessieRepo.ReadAndInclude(session => session.SessieDeelnames).ThenInclude(/* ??? */);
My intellisense не распознает тип свойства, явно связанного цепочкой
Если вы спросите меня, я бы сказал, что это связано с тем, что тип возвращаемого значения моего метода:
IIncludableQueryable<T, object> //<- object is the problem
Это то, что я считаю неправильным, но я понятия не имею, как указать фактический тип класса свойства. Я не уверен, но если я просматриваю документацию для ThenInclude (), я вижу, что они используют отражение, чтобы выяснить, какой тип свойства? Поправьте меня, если я ошибаюсь.
Предложения, решения или замечания по пересекающейся архитектуре приветствуются.