Reputation: 11255
I'd like to load a Test
by id including all related TestRuns
and all Measurements
using DbContext/EntityFramework from a MySql database.
This is the database schema:
What I tried so far:
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));
}
}
Unfortunately this takes a very long time to complete (about one minute for 1 Test/1 Testrun/15000 Measurements). I tried to understand the generated SQL code by using a query profiler, but couldn't make sense of the huge monster SQL statement.
Can you think of a better (i.e. faster) way to load the data using DbContext?
Update
Another try, also resulting in a looong loading time:
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;
}
Loading the measurements takes 84% of the time:
This is the corresponding sql statement for fetching the measurements:
SELECT
Extent1.id,
Extent1.test_run_id,
Extent1.rss_dbm
FROM measurement AS Extent1
WHERE Extent1.test_run_id = :EntityKeyValue1
I copied each of the resulting sql statements (from the three DbContext
/DbSet
queries) from the query profiler into MySqlWorkbench, and each for itself is running very fast. Now I am even more confused...
Update 2
I isolated the function GetTestComplete
(see above) in a single unit/performance test and it still takes a long time. The output of the query profiler shows that the individual sql commands are very fast, even though the whole test takes about 5 seconds to complete.
Confusion growing...
Upvotes: 3
Views: 1892
Reputation: 109079
Executing a query is one thing. EF will do that very fast. Quite another thing is materializing entity objects, creating DbEntityEntry
and relationship objects for the change tracker.
If you fetch entities by...
DbSet.AsNoTracking()
...creating these DbEntityEntry
s is taken out of the process, which usually considerably increases performance.
If you apply AsNoTracking
, you can only use Include
to load related entities. A statement like...
DbContext.Entry(testRun).Collection(tr => tr.Measurements).Load();
...will fail, because there won't be an entry for testRun
in the first place, and the Load
method is the opposite of AsNoTracking
, sort of, because it is designed to load tracked entities into a context without returning them.
Upvotes: 2
Reputation: 2936
http://msdn.microsoft.com/pl-pl/library/bb738708%28v=vs.110%29.aspx - try this, but I have no idea about performance
Upvotes: -1