Документация для DbQuery<T>.Include(path)
состояний, (пожалуйста, прочитайте ПРИМЕЧАНИЯ в конце - он описывает, как путь, включая работу):
Пути Все- включительно. Например, если входящий вызов указывает Include («Orders.OrderLines»), будут включены не только OrderLines, , но и Заказы.
Так что k.Appointment.Provider.Address
будет включать k.Appointment
в любом случае. Даже если нет производительности, второй запрос лучше, потому что он не содержит повторяющихся включений.
UPDATE: Разница в производительности в запросе базы данных не будет, поскольку в обоих запросах LINQ будет создан один и тот же SQL-запрос (ну, порядок LEFT OUTER JOINS может отличаться). Но при генерации запроса будет небольшая разница в производительности, потому что когда вы включаете какой-то путь, будет создан новый ObjectQuery
(да, каждый Include
создает новый запрос вместо изменения существующего).
ПРИМЕЧАНИЕ: Было интересно узнать, почему нет разницы. Я провел некоторое исследование источников Entity Framework 6 и нашел способ, которым EF собирает пути, которые должны быть включены. Существует внутренний закрытый класс Span
, который содержит коллекцию путей для определения того, какие элементы включены в запрос. SpanPath
очень просто - это просто обертка на список строк, которые представляют плавания быть включено:
internal class SpanPath
{
// you can think naviagations as path splitted by dots
public readonly List<string> Navigations;
// ...
}
И Span
это класс, который содержит все включенные пути:
internal sealed class Span
{
private readonly List<SpanPath> _spanList = new List<SpanPath>();
public void Include(string path)
{
Check.NotEmpty(path, "path");
SpanPath spanPath = new SpanPath(ParsePath(path));
this.AddSpanPath(spanPath);
}
internal void AddSpanPath(SpanPath spanPath)
{
if (this.ValidateSpanPath(spanPath))
{
this.RemoveExistingSubPaths(spanPath);
this._spanList.Add(spanPath);
}
}
private bool ValidateSpanPath(SpanPath spanPath)
{
for (int i = 0; i < this._spanList.Count; i++)
{
if (spanPath.IsSubPath(this._spanList[i]))
return false;
}
return true;
}
}
Итак, вот что происходит - когда вы включаете новый путь, то:
- Он расщепляется в список строк и заворачивают в SpanPath
- Если текущий путь является подпутью некоторого уже добавленного пути, мы просто игнорируем его.
- В противном случае мы проверяем, существует ли в наших навигационных переходах текущий путь. Если это так, мы удалим все подпуты
- Теперь мы можем добавить новый путь.
Когда вы включаете Appointment.Provider.Address
путь в первом случае, то Appointment
путь будет удален на шаге 3, потому что к югу от пути Appointment.Provider.Address
.
РЕЗЮМЕ:
явно не включает в себя подпуть в запросе - это вызовет в создании нового экземпляра ObjectQuery, и это не повлияет на сгенерированный запрос. Он будет либо проигнорирован, либо будет удален, когда вы добавите путь, который включает этот.
Вы пытались запустить оба запроса? –
@SergeyBerezovskiy Yes.Out положить то же самое. – Sampath