Вот самая базовая реализация вашей someMethod
процедуры:
private void someMethod<S, T, P>(
IQueryable<S> source,
IQueryable<T> target,
Func<S, P> sourceSelector,
Func<T, P> targetSelector)
{
foreach(var s in source)
{
var sp = sourceSelector(s);
var @object = target
.Where(t => targetSelector(t).Equals(sp)).FirstOrDefault();
//...
}
}
Эта реализация сохраняет структуру вашего исходного кода, но это обходится дорого.Вы эффективно делаете source.Count() * target.Count()
запросов к вашей базе данных.Вам нужно отказаться от использования foreach
при работе с IQueryable<>
.
На самом деле, когда вы начинаете писать код с foreach
, вам нужно спросить себя, можете ли вы использовать запрос LINQ для сборкии отфильтруйте ваши данные и заставьте цикл foreach
выполнять только «самые простые» задачи.
Вот как улучшить работу метода:
private void someMethod2<S, T, P>(
IQueryable<S> source,
IQueryable<T> target,
Expression<Func<S, P>> sourceSelector,
Expression<Func<T, P>> targetSelector)
{
var query = source
.GroupJoin(
target,
sourceSelector,
targetSelector,
(s, ts) => ts.FirstOrDefault());
foreach(var @object in query)
{
//...
}
}
Обратите внимание на использование Expression<Func<,>>
и не только Func<,>
.Также обратите внимание на вызов метода GroupJoin
.