使用linq的EntityFramework很慢

时间:2016-06-01 12:15:29

标签: c# entity-framework linq

我试图让我的实体只有一些孩子(一个),但我的要求非常慢。

我的课程是:

  • '电路' :包含' etape'
  • 的列表
  • ' Etape酒店' :包含'问题'
  • 的列表

我想过滤我的电路,从每个电路的第一个etape获得一些地理位置,并获得所有匹配我的滤波器但仅与我的电路的第一个etape匹配的电路实体。 (所以我的过滤电路与numEtape == 1)的etape。 我只想要第一个etape,因为它可以是每个电路10,20,30 .. etapes,所以为了减少我的查询的迟到。

这是我现在的查询,它可能非常慢,仅需要20 000个电路进行过滤。 (但是使用X etape,etape有Y问题..)

var x = db.circuit.Include("etape").Include("etape.question")
    .Where(
        c => c.etape.Count() >= 2 &&
        c.enabled &&
        !circuitsAfficher.Contains(c.id) &&
        (
            c.etape.Where(e => e.numEtape == 1).FirstOrDefault().posLat > xbottom &&
            c.etape.Where(e => e.numEtape == 1).FirstOrDefault().posLat < xtop
        ) &&
        (
            c.etape.Where(e => e.numEtape == 1).FirstOrDefault().posLong < yright &&
            c.etape.Where(e => e.numEtape == 1).FirstOrDefault().posLong > yleft
        )
    )
    .Select(p => new
        {
            circuit = p,
            etape = p.etape.Where(c => c.numEtape == 1)
        }).ToList();
编辑:感谢@Ivan Stoev工作的新代码

 listFiltred = db.circuit.AsNoTracking().Where(
                c => c.etape.Count() >= 2 &&
                c.enabled &&
                !circuitsAfficher.Contains(c.id) &&
                c.etape.Any(e => e.numEtape == 1 &&
                e.posLat > Xbottom && e.posLat < Xtop &&
                e.posLong < yright && e.posLong > Yleft))                      
                   .Select(p => new CircuitWithEtape
                   {
                       circ = p,
                       firstetape = p.etape.Where(c => c.numEtape == 1).FirstOrDefault()
                   }).ToList();

CircuitWithEtape类:

   public class CircuitWithEtape
    {
        public circuit circ { get; set; }
        public etape firstetape { get; set; }
    }

此时我有一个电路清单,所有的etape与他的第一个etape(firstetape)配对。

1 个答案:

答案 0 :(得分:1)

您可以使用基于Any的单一条件替换所有基于c.etape.Where(e => e.numEtape == 1).FirstOrDefault()的条件(我怀疑每个条件生成一个子查询):

.Where(
    c => c.etape.Count() >= 2 &&
    c.enabled &&
    !circuitsAfficher.Contains(c.id) &&
    c.etape.Any(e => e.numEtape == 1 &&
        e.posLat > xbottom && e.posLat < xtop &&
        e.posLong < yright && e.posLong > yleft)
)

应在主查询中生成单个EXISTS (subquery)条件。

编辑:查看最终查询,以下情况可能会更好:

listFiltred = 
    (from c in db.circuit.AsNoTracking()
         .Where(c => c.etape.Count() >= 2 && 
             c.enabled &&
             !circuitsAfficher.Contains(c.id))
     from e in c.etape
         .Where(e => e.numEtape == 1 &&
             e.posLat > Xbottom && e.posLat < Xtop &&
             e.posLong < yright && e.posLong > Yleft)
     select new CircuitWithEtape
     {
         circ = c,
         firstetape = e
     }).ToList();