Моей контекстная модель имеет несколько связанных таблицы:Нужна помощь построение 4 запроса Entity Framework
CREATE TABLE "CarSystem"."Reads" (
"ReadId" UUID PRIMARY KEY,
. . .
);
CREATE TABLE "CarSystem"."Alarms" (
"AlarmId" UUID PRIMARY KEY DEFAULT UUID_GENERATE_V4(),
"ReadId" UUID NOT NULL REFERENCES "CarSystem"."Reads" ("ReadId"),
. . .
);
Есть другие столбцы, но они не важны. Между таблицей Reads и таблицей Alarms существует соотношение «0». В таблице Alarms может быть любое количество строк для каждой строки в таблице Reads, начиная с нуля.
У меня есть модель Entity Framework для этой структуры базы данных. У меня также есть объект ViewModel для строк в таблице Reads. Я хочу, чтобы объект ViewModel имел логическое свойство, называемое HasAlarms. Это свойство должно быть установлено в true, если в таблице Alarms для строки в таблице Reads есть хотя бы одна строка.
У меня есть функция на моем уровне доступа к данным, которая должна возвращать массив объектов Read ViewModel, которые соответствуют набору критериев. Я не уверен, как построить запрос для установки свойства HasAlarms. Я хочу только один раз перейти к базе данных, и мне нужна одна запись в массиве для каждой строки в таблице Reads.
Прямо сейчас я делаю два запросов к базе данных, один, чтобы получить все читает, а другой, чтобы получить все Сигнализации:
IQueryable<Read> query = from read in context.Reads
where SomeCondition
select read;
Alarm[] alarms = (from read in query
join alarm in context.Alarms on read.Readid equals alarm.ReadId
select alarm).ToArray();
ReadViewModel[] result = (from read in query
select new ReadViewModel {
ReadId = read.ReadId,
. . .
HasAlarms = alarms.Where(a => a.ReadId == read.ReadId).Any(),
. . .
}).ToArray();
Это работает, но это неэффективно, потому что я ударяя базу данных дважды, один раз, чтобы получить строки в таблице Reads и один раз, чтобы получить Alarms.
Есть ли способ построить этот запрос, чтобы он только ударил базу данных один раз?
Тони
@Craig Stuntz:
То, что я пытаюсь сделать, это ускорить скорость, с которой загружаются данные в моем приложении в ответ на запрос отчета. Это приложение WPF, и мне нужно, чтобы данные загружались как можно быстрее, чтобы улучшить работу пользователя. Важно сделать как можно меньше поездок в базу данных, или приложение, похоже, сканирует.
Объект ReadViewModel состоит из свойств, которые сопоставляются с столбцами в таблице, плюс несколько вложенных объектов, которые либо хранятся в виде столбцов в одной таблице, либо как строки в нескольких связанных таблицах. Это сложная структура, и Entity Framework жалуется, если я попытаюсь создать объект View Model с одним IQueryable. То есть, что-то вроде:
ReadViewModel[] reads = (from read in context.Reads
join alarm in context.Alarms on read.ReadId equals alarm.ReadId
where SomeCondition
select new ReadViewModel { ... }).ToArray();
генерирует исключение, которое говорит Entity Framework не может создать константу одного из вложенных типов.
Если я извлекаю данные в массивы объектов Entity, а затем создаю объекты View Model с помощью Linq, все работает. Но тогда мне нужно сделать несколько поездок в базу данных, чтобы получить все. Однако, если я получаю все данные с этими запросами, это намного быстрее, чем позволить Entity Framework вернуться и запросить дополнительные данные для каждой строки, что происходит, когда я делаю это так, как вы рекомендуете. Также возникает сложность сделать левое внешнее соединение с таблицей Alarms, чтобы все испортить.
Я обнаружил, что если я сначала получаю массивы объектов Entity, вместо того, чтобы совершать одну поездку для каждой строки в дополнение к первоначальной поездке, я могу сделать 2 или 3 общей поездки. Это намного быстрее, чем n + 1 или n + 2 поездки. Я просто пытался понять, есть ли способ заставить Entity Framework делать все это в одном вызове базы данных, что я мог бы легко сделать, если бы сам писал SQL.Мне просто нужно добавить столбец, который возвращает 0 или 1 для HasAlarms, если в таблице Alarms для Read есть хотя бы одна строка.
Plesase см. Мое редактирование оригинального вопроса. –
Запрос, который я дал вам, получает весь результат в одном раунде. –