Ответ 1
Немного поздно, но, поскольку ваши данные меняются один раз в день, взгляните на то, чтобы положить все необходимое в индексированное представление и поместить это представление в свою модель EF.
Я использую EF (версия dll 4.4) для запроса к базе данных. База данных содержит несколько таблиц с информацией о курсе. Когда вы посмотрите, что на самом деле отправлено в db, я вижу массивный, почти 1300 строк SQL-запрос (который я не собираюсь вставлять здесь из-за его размера). Запрос, который я запускаю в контексте, выглядит следующим образом:
entities.Plans
.Include("program")
.Include("program.offers")
.Include("program.fees")
.Include("program.intakes")
.Include("program.requirements")
.Include("program.codes")
.Include("focuses")
.Include("codes")
.Include("exceptions")
.Include("requirements")
where plans.Code == planCode
select plans).SingleOrDefault();
Я хочу избежать необходимости возвращаться на сервер при сборе информации из каждой из связанных таблиц, но с таким большим запросом мне интересно, есть ли лучший способ сделать это?
Спасибо.
Немного поздно, но, поскольку ваши данные меняются один раз в день, взгляните на то, чтобы положить все необходимое в индексированное представление и поместить это представление в свою модель EF.
Обычно вы можете добавить .Include()
после предложения where. Это означает, что вы вынимаете только информацию, которая соответствует тому, что вы хотите, посмотрите, не уменьшит ли ваш запрос какой-либо.
Как вы выполняете активную загрузку, поэтому, если вы выбираете требуемые объекты, то это нормально. В противном случае вы можете пойти с Lazy Loading, но поскольку вы указали, что вам не нужна база данных в оба конца, вы можете ее избежать.
Я бы предположил, что если этот запрос используется несколько раз, вы можете использовать скомпилированный запрос. Чтобы повысить производительность,
Пройдите по этой ссылке, если хотите.. http://msdn.microsoft.com/en-us/library/bb896297.aspx
Если вы используете DbContext
, вы можете использовать свойство .Local
в контексте, чтобы посмотреть, уже ли ваш объект уже извлечен и поэтому привязан к контексту.
Если запрос выполнялся раньше, и ваши корневые объекты Plan
уже привязаны на основе Plan.Code == planId
, предположительно его суб-сущности также уже прикреплены, так как вы действительно загружаете загрузку, поэтому ссылайтесь на них через свойства навигации, t поражает БД для них снова в течение жизни этого контекста.
Эта статья может оказаться полезной при использовании .Local
.
Возможно, вы сможете получить чуть более сжатый SQL-запрос, используя прогноз, а не Include
, чтобы отбросить ваши ссылочные объекты:
var planAggregate =
(from plan in entities.Plans
let program = plan.Program
let offers = program.Offers
let fees = program.Fees
//...
where plan.Code == planCode
select new {
plan
program,
offers,
fees,
//...
})
.SingleOrDefault();
Если вы отключите ленивую загрузку в своем контексте, такой запрос приведет к тому, что свойства навигации ваших объектов будут заполнены объектами, включенными в ваш запрос.
(Я тестировал это только на EF.dll v5.0, но он должен вести себя одинаково на EF.dll v4.4, который является только EF5 на .NET 4.0. Когда я тестировал этот шаблон, а не Include
в запросе аналогичной формы он вырезает около 70 строк из 500 строк SQL. Ваш пробег может отличаться.)