Я использую EF для набора объектов и хочу запросить один тип объекта с соответствующими записями из двух других таблиц. Это для выгрузки запроса в вывод XML. Сначала использовалось объединение, поскольку в исходных данных каждый Сотрудник всегда имел 1+ экземпляров объекта Компьютер (решение № 2 ниже), но это не обязательно так.
Для цели представьте:
- и Сотрудник объект,
- каждый сотрудник имеет EmployeeType (несколько фиксированных записей) и
- каждый сотрудник имеет ноль или более компьютер объекты (обычно 0-3).
- каждый компьютер принадлежит одному сотруднику, не у каждого сотрудника есть компьютер.
- У каждого сотрудника есть критерии, на которых основан поиск (например, Отдел ).
Итак, я увидел несколько возможных решений:
Используйте Employee.Computer.Load () внутри цикла, но с 10 000+ строками, что приводит к огромным потерям производительности.
Используйте объединение в запросе, но это исключает всех Сотрудников , у которых нет Компьютера .
Используйте Linq to Entities, , но это, похоже, накладные расходы # 1: при загрузке Компьютер s он попадает в базу данных для каждого Сотрудник .
Используйте второй запрос (все Компьютер s с соответствующими Computer.Employee.Division ), затем в цикле Employee добавьте любой Компьютер для данного сотрудника. При реализации этого я обнаружил, что, просто выполняя второй запрос (с ToList () ), EF заполняет корректные списки Employee.Computer нужными мне объектами. *
Здесь # 4 загружает данные только с 2 попаданиями в базу данных вместо 10k +, и EntityFramework фактически объединяет объекты и создает все отношения.
Мои вопросы :
- С # 4, является ли факт, что EF заполняет список Employee.Computer , на который я могу положиться? Если да, можете ли вы указать мне документацию?
- Есть ли лучший способ, чем # 4?
UPDATE :
Ну, черт возьми. Извините, но я просто взорвал это. Я сосредоточился на
связь с таблицей «Компьютер» и пропустил тот факт, что я
было явное Employee.EmployeeTypeReference.Load () без первого тестирования
для нуля, так что список «Компьютер» был совершенно не проблема.
Я обнаружил это только при запуске некоторых тестов производительности и добавлении
Решение Крейга для смеси. По правде говоря, записи не "сотрудники"
и "Компьютеры", но абстракции, и я (условно) включаю каждый
поля в выводе XML, но они малы: имя, идентификатор (PK) и идентификатор (FK)
плюс INT в таблице «Сотрудник». Итак, я предполагаю, что
производительность будет аналогичной, так как EF будет создавать объекты не
намного тяжелее, чем проекция.
В любом случае, вот результаты, когда "прошедшее" время было
разница до этого запроса и после создания результирующего XML.
Случай 1: То же, что и № 2, но с Включить () заявления:
list = ve.Employee.Include("Computer").Include("EmployeeType").Where(e => e.Division.ID == divId).OrderBy(e => e.Name);
Прошло: 4,96, 5,05
Случай 2: используется in-line Load () :
list = ve.Employee.Where(e => e.Division.ID == divId).OrderBy(e => e.Name);
Прошло: 74,62
Случай 3: То же, что и # 4, но с Включить () заявления:
list = from e in ve.Employee.Include("Computer").Include("EmployeeType")
where e.Division.ID == divId
orderby e.Name select e;
Прошло: 4,91, 5,47
Случай 4: используется in-line Load () :
list = from e in ve.Employee where e.Division.ID == divId orderby e.Name select e;
Прошло: 74.20
Случай 5: используйте * Include ("EmployeeType") и отдельный запрос "Computer", позвольте EF связываться:
elist = ve.Employee.Include("EmployeeType").Where(te => te.Division.ID == divId).OrderBy(e => e.Name).ToList();
alist = ve.Alias.Where(a => a.Employee.Division.ID == divId).ToList();
Прошло: 4,50, 4,02
Случай 6: предложение Крейга о проекциях:
elist = from te in ve.ThesaurusEntry where te.Division.ID==divID
orderby te.Name select new {
ID = te.ID, Name = te.Name,
Type = te.EmployeeType.Name,
Freq = te.Frequency,
Aliases = from a in te.Alias
select new {
ID = a.ID, Name = a.Name
}
};
Прошло: 0,73, 1,25
Выводы
Load () стоит дорого, поэтому используйте Include () или хотя бы тестируйте с IsLoaded
Проецирование немного утомительно, но значительно быстрее, чем исправление EF. [с этим ограниченным тестированием на «узких» таблицах]