簡體   English   中英

實體框架LINQ加快了將SQL數據轉換為C#對象的速度

[英]Entity framework LINQ speed converting SQL data into C# objects

我有一個用LINQ編寫的相當復雜的查詢,它查詢我的數據庫。 我已經確保只從每個實體中拉回相關的列,因此查詢盡可能地細,因此LINQ填充的對象也不包含任何不必要的列。

如果我直接對數據庫運行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();

是! 我不久前也遇到類似的事情。 我想到的是在LINQ中使用AsParallel()函數...但是,這帶有一些警告。

  1. 您將並行運行事物-很明顯,但是如果您嘗試以非線程安全的方式運行事物,則可能會出現問題
  2. 這僅在某些情況下才有用-我最大程度地利用它的方式是當我將許多數據庫行轉換為C#對象並重復執行此操作時...考慮foreach,for,while循環不會它們中有任何決策邏輯,但只有直接的數據庫行到C#類的轉換
  3. 這實際上僅對“大量”數據有意義-您將不得不處理這一點,看看時間上的差異是什么,但是如果您僅轉換少量行,則AsParallel()的開銷實際上將花費您更多的時間,卻沒有為您節省任何時間。

這是有關AsParallel()的更多閱讀內容,希望對您有所幫助!

https://msdn.microsoft.com/zh-cn/library/vstudio/dd413237%28v=vs.100%29.aspx-AsParallel方法

https://msdn.microsoft.com/zh-cn/library/dd997425%28v=vs.110%29.aspx-並行查詢簡介

http://www.dotnetperls.com/asparallel-AsParallel的基本入門

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM