实体框架LINQ将SQL数据转换为C#对象

时间:2015-04-09 12:33:07

标签: c# linq entity-framework linq-to-entities

我有一个用LINQ编写的相当复杂的查询来查询我的数据库。我已经确定我只是从每个实体中撤回相关列,因此查询尽可能简洁,因此LINQ填充的对象也不包含任何不必要的列。

如果我直接对DB执行LINQ查询生成的SQL,那么SQL将在大约4秒内运行。但是,从我的LINQ查询执行此操作大约需要25秒。这25秒的大部分时间都被返回的DB数据写入对象。

在执行这部分操作时,是否有任何有用的技巧可以帮助LINQ / Entity Framework解决?

编辑:

当我在下面的查询中调用ToList()方法时发生长延迟:

var q1 = from u in etc.Users
         where (u.flags & (int)UserFlags.Student) == (int)UserFlags.Student
         && (ariStudents.Contains(u.id) || ariStudents.Count == 0)
         && (from ua in etc.UserAssociations where ua.datasetId == datasetId && ua.userId == u.id && ua.type == (int)UserAssocTypes.EnrolActive select ua).Any()
         orderby u.id
         select new ElightsRaw2
         {
             Student = new ElrStudent{StudentId = u.id},
             StudentData = (
                    from sd in etc.StudentDatas
                    where sd.userId == u.id
                    && sd.datasetId == datasetId
                    select new ElrStudentData { attP = sd.attP, attA = sd.attA, attL = sd.attL }
                ).FirstOrDefault(),
             ElightOverall = (
                    from els in etc.eLightsStudents
                    where els.datasetId == datasetId
                    && els.userId == u.id
                    select els
                ).FirstOrDefault(),
             Groups = (
                 // get all courses and groups for user
                    from c in etc.Cours
                    join g in etc.Groups on c.id equals g.courseId
                    join ua in etc.UserAssociations on g.id equals ua.fkId
                    where ua.datasetId == datasetId
                    && ua.userId == u.id
                    && ua.type == (int)UserAssocTypes.EnrolActive
                    && (ua.flags & (int)UserAssociationFlags.AssociationDeleted) == 0
                    && (c.flags & (int)CourseFlags.Deleted) == 0
                    select new ElrGroupHolder
                    {
                        CourseName = c.name,
                        GroupName = g.name,
                        Breakdown = new ElrGroupHolderBreakdown
                        {
                            UnitsBelowScoreThresh1 = (
                                    from uus in etc.UserUnitScores
                                    join un in etc.Units on uus.unitId equals un.id
                                    join cu in etc.CourseUnits on un.id equals cu.unitId
                                    where uus.userId == u.id
                                    && (un.flags & (int)UnitFlags.Deleted) == 0
                                    && (cu.flags & (int)CourseUnitFlags.NotStarted) == 0
                                    && cu.courseId == c.id
                                    && (uus.performance > -1 && uus.performance <= amberThresh)
                                    && !(from exc in etc.UserAssociations where exc.userId == u.id && exc.fkId == un.id && exc.type == (int)UserAssocTypes.ExcludedUnit select exc).Any()    // not excluded from unit
                                    select uus
                                ).Count(),
                            UnitsBelowScoreThresh2 = (
                                    from uus in etc.UserUnitScores
                                    join un in etc.Units on uus.unitId equals un.id
                                    join cu in etc.CourseUnits on un.id equals cu.unitId
                                    where uus.userId == u.id
                                    && (un.flags & (int)UnitFlags.Deleted) == 0
                                    && (cu.flags & (int)CourseUnitFlags.NotStarted) == 0
                                    && cu.courseId == c.id
                                    && (uus.performance > -1 && uus.performance <= redThresh)
                                    && !(from exc in etc.UserAssociations where exc.userId == u.id && exc.fkId == un.id && exc.type == (int)UserAssocTypes.ExcludedUnit select exc).Any()    // not excluded from unit
                                    select uus
                                ).Count(),
                            CfcCount = (
                                    from cfc in etc.CFCs
                                    where cfc.datasetId == datasetId
                                    && cfc.studentId == u.id
                                    && cfc.dt > dCfcCutoff
                                    && cfc.type == (int)CfcTypes.Concern
                                    && (cfc.flags & (int)CfcFlags.Deleted) == 0
                                    && (
                                        // only include attendance and behaviour CFCs
                                        (cfc.flags & (int)CfcFlags.Attendance) == (int)CfcFlags.Attendance
                                        || (cfc.flags & (int)CfcFlags.Behaviour) == (int)CfcFlags.Behaviour
                                    )
                                    select cfc
                                ).Count(),
                            SrsScores = (
                                    from srs in etc.SRScores
                                    join sr in etc.SubReviews on srs.srId equals sr.id
                                    where sr.datasetId == datasetId
                                    && (sr.flags & (int)SrFlags.Deleted) == 0
                                    && (srs.flags & (int)SrsFlags.Deleted) == 0
                                    && sr.dt > dCfcCutoff
                                    && sr.userId == u.id
                                    && sr.courseId == c.id
                                    select new ElrSrScore
                                    {
                                        attainment = srs.attainment,
                                        attitude = srs.attitude,
                                        motivation = srs.motivation,
                                        studyskill = srs.studyskill
                                    }
                                ).ToList(),
                            ElightEnrolment = (
                                    from ele in etc.eLightsEnrolments
                                    where ele.datasetId == datasetId
                                    && ele.groupId == g.id
                                    && ele.userId == u.id
                                    select ele
                                ).FirstOrDefault(),
                        },
                        CourseAttendance = (
                                from a in etc.Attendances
                                where a.studentId == u.id
                                && a.courseId == c.id
                                && a.weekNumberId == null
                                && a.datasetId == datasetId
                                select a
                            ).FirstOrDefault()
                    }
                ).ToList(),
         };

return q1.ToList();

1 个答案:

答案 0 :(得分:0)

是的!不久前我遇到了类似的事情。我想出的是在LINQ中使用AsParallel()函数......但是这有一些注意事项。

  1. 你将并行运行 - 显而易见但是如果你试图以非线程安全方式做事可能会有问题
  2. 这只会在某些情况下有用 - 我最常使用的方式是当我将大量数据库行转换为C#对象并重复执行时...想想foreach,for,while循环其中没有任何决策逻辑,只有一个直接的数据库行到C#类转换
  3. 它实际上只对“大量”数据有意义 - 你将不得不玩这个并看看时间差异是什么,但如果你只是转换少量行,AsParallel的开销( )实际上会花费你更多的时间,而不是拯救你。
  4. 以下是关于AsParallel()的更多阅读,希望这有帮助!

    https://msdn.microsoft.com/en-us/library/vstudio/dd413237%28v=vs.100%29.aspx - AsParallel Method

    https://msdn.microsoft.com/en-us/library/dd997425%28v=vs.110%29.aspx - 并行查询简介

    http://www.dotnetperls.com/asparallel - AsParallel的基本演练

相关问题