1

我有EF,首先是数据库。我有三个模型类ABC。模型与A具有 m2m 关系,B并且与B具有 m2m 关系C

我列出了A与相关B和的子集C

在测试环境中,子集中有大约 20 个模型A,只有少数有任何相关B,如果有,在大多数情况下它只是一个。

模型B一直只有一个相关C的。我不想更改它,因为将来会有更多C与 one 相关的内容B

我的第一种方法是:

var listA = new Entities(...).As.Where(...).ToList();
foreach (var objA in listA){
    var listC = objA.Bs.ToList().Select(b => b.FirstOrDefault(c => ...)).ToList();
}

它花了大约 164 毫秒 - 相当长。

所以我想优化它。

如您所见,在第一行IQueryable<A>更改为List<A>. 我认为,此时此刻,查询已被执行。

当我想获得BsforACforB时,我认为会执行另一个查询。

然后我搜索并找到了Include方法。在第二种方法中,我像这样使用它:

var listA = new Entities(...).As.Include("Bs.Cs").Where(...).ToList();
foreach (var objA in listA){
    var listC = objA.Bs.ToList().Select(b => b.FirstOrDefault(c => ...)).ToList();
}

在我看来,执行应该需要大约 10 毫秒,但现在需要 550 毫秒。

当我只是列出As没有相关BsCs内容时,大约需要 10 毫秒。

我究竟做错了什么?

编辑:抱歉,C 对 B 有 FK。但我认为它不会改变任何东西。

4

2 回答 2

0

如果您的 DbContext 支持“默认情况下为真”的延迟加载,那么每当您调用时都会对数据库产生很多命中objA.Bs.ToList()b => b.FirstOrDefault(c => ...) 那是因为您没有在第一个listA查询中包含这些导航属性。

无论如何尝试使用 Include 方法

var listA = new Entities(...).As.Include("Bs").Include("Bs.Cs").Where(...).ToList();
于 2012-11-27T10:03:57.910 回答
0

根据我的经验,相关对象的显式加载要快一些。请尝试使用对象 Load() 方法加载并使用 IsLoaded 检查它是否已加载。另外关闭延迟加载和显式打开连接可能会有所帮助。

类似以下内容可能会有所帮助。

var listA = from o in context where (...) select o;
foreach (var i in listA)
            {
                if (!i.Bs.IsLoaded)
                    i.Bs.Load();
                if (i.Bs != null)
                {
                    if (!i.Bs.Cs.IsLoaded)
                        i.Bs.Cs.Load();
                }

            }
于 2012-12-03T14:05:21.937 回答