Я хочу загрузить Test
по идентификатору, включая все связанные TestRuns
и все Measurements
, используя DbContext/EntityFramework из базы данных MySql.
Это схема базы данных:
Что я пробовал до сих пор:
public class TestRepository : Repository<Test>, ITestRepository
{
public IQueryable<Test> GetTestComplete(int id)
{
return DbSet.Where(t => t.Id == id)
.Include(t => t.TestRuns.Select(tr => tr.Measurements));
}
}
К сожалению, это занимает очень много времени (около одной минуты для 1 теста/1 теста/15000 измерений). Я попытался понять сгенерированный код SQL с помощью профилировщика запросов, но не смог разобраться в этом огромном монструозном операторе SQL.
Можете ли вы придумать лучший (то есть более быстрый) способ загрузки данных с помощью DbContext?
Обновить
Еще одна попытка, также приводящая к долгому времени загрузки:
public Test GetTestComplete(int id)
{
Test test = DbSet.Find(id);
DbContext.Entry(test).Collection(t => t.TestRuns).Load();
foreach (var testRun in test.TestRuns)
{
// next line takes a lot of time!
DbContext.Entry(testRun).Collection(tr=>tr.Measurements).Load();
}
return test;
}
Загрузка измерений занимает 84% времени:
Это соответствующий оператор sql для получения измерений:
SELECT
Extent1.id,
Extent1.test_run_id,
Extent1.rss_dbm
FROM measurement AS Extent1
WHERE Extent1.test_run_id = :EntityKeyValue1
Я скопировал каждый из результирующих операторов sql (из трех запросов DbContext
/DbSet
) из профилировщика запросов в MySqlWorkbench, и каждый сам по себе работает очень быстро. Теперь я еще больше запутался...
Обновление 2
Я изолировал функцию GetTestComplete
(см. выше) в одном тесте модуля/производительности, и это все еще занимает много времени. Выходные данные профилировщика запросов показывают, что отдельные команды sql выполняются очень быстро, несмотря на то, что весь тест занимает около 5 секунд. Растерянность растет...
DbSet.AsNoTracking()
. Я думаю, что много времени уходит на менеджер состояния объекта и исправление отношений. Если вам нужно изменить данные, я думаю, вы должны попытаться получить только то, что вам нужно изменить. - person Gert Arnold   schedule 12.12.2014DbSet.AsNoTracking()
сделает свое дело и сократит время запроса измерений с 4 с до 400 мс. Но как использоватьAsNoTracking()
с этим запросомDbContext.Entry(testRun).Collection(tr => tr.Measurements).Load();
? - person nabulke   schedule 12.12.2014