我想使用 DbContext / EntityFramework 加载Test
ID,包括所有相关的TestRuns
和所有Measurements
来自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次Testrun / 15000测量大约需要1分钟)。我试图通过使用查询分析器来理解生成的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秒钟才能完成。
混乱增长......
答案 0 :(得分:2)
执行查询是一回事。 EF将非常快速地做到这一点。另一件事是实现实体对象,为更改跟踪器创建DbEntityEntry
和关系对象。
如果您按...获取实体
DbSet.AsNoTracking()
...创建这些DbEntityEntry
的过程会被取消,这通常会大大提高性能。
如果您应用AsNoTracking
,则只能使用Include
加载相关实体。像......这样的陈述。
DbContext.Entry(testRun).Collection(tr => tr.Measurements).Load();
...会失败,因为首先不会成为testRun
的条目,和 Load
方法与{ {1}},因为它旨在将跟踪的实体加载到上下文中而不返回它们。
答案 1 :(得分:-1)