2017-01-02 39 views
0

我之前提出過這個問題,因爲我沒有提供代碼,因此投了票。但我堅信我的問題不是代碼相關的,我非常渴望解決這個問題。LINQ查詢在服務器上超時,但立即在本地執行

基本上,我需要從LINQ查詢中得到2個不同的東西的計數,查詢正在建立並且很長。

奇怪的是:當在數據庫服務器上執行選擇的LINQ查詢時,它會在第二次計數(無論設置CommandTimeout多長時間)超時,但是當我從數據庫服務器,並把它放在我的本地,然後執行LINQ查詢它立即得到兩個計數。

I SQL Profiler數據庫服務器和本地服務器上的已翻譯的SQL查詢,它們是相同的。當從本地生成的已翻譯SQL查詢手動運行在數據庫服務器的SQL Management Studio上時,它也會立即返回計數。

這就是爲什麼我高度懷疑它不是像許多人所建議的代碼問題或N + 1問題。我懷疑它是一個環境問題,但這超出了我的理解爲什麼會發生這種情況。如果有人曾經遇到過這個問題,有人可以提供意見嗎?如果您需要LINQ代碼,請讓我知道我可以縮短它並上傳。

 IQueryable<StudentDm> studentQuery = GetListQuery(); 
     IQueryable<StudentTestDm> studentTestQuery = studentQuery.SelectMany(a => a.StudentTests); 

     if (studentAcademicTestProficiencyGrowthParameter.TestTypeId.HasValue) 
     { 
      studentTestQuery = studentTestQuery.Where(a => a.TestTypeId == studentAcademicTestProficiencyGrowthParameter.TestTypeId); 
     } 

     DateTime serviceDateFrom = (studentAcademicTestProficiencyGrowthParameter.ServiceDateFrom.HasValue) ? studentAcademicTestProficiencyGrowthParameter.ServiceDateFrom.Value : DateTime.MinValue; 
     DateTime serviceDateTo = (studentAcademicTestProficiencyGrowthParameter.ServiceDateTo.HasValue) ? studentAcademicTestProficiencyGrowthParameter.ServiceDateTo.Value : DateTime.MaxValue; 

     // test 1 query 
     IQueryable<StudentTestDm> studentTest1Query = studentTestQuery; 

     if (studentAcademicTestProficiencyGrowthParameter.Test1SchoolYear.HasValue) 
     { 
      studentTest1Query = studentTest1Query.Where(a => a.Year == studentAcademicTestProficiencyGrowthParameter.Test1SchoolYear); 
     } 

     if (studentAcademicTestProficiencyGrowthParameter.Test1TestDate.HasValue) 
     { 
      studentTest1Query = studentTest1Query.Where(a => a.TestDate == studentAcademicTestProficiencyGrowthParameter.Test1TestDate); 
     } 

     // we grab the grouped students who has non-proficient test, and who does not have proficient test 
     IQueryable<IGrouping<StudentDm, StudentTestDm>> groupedStudentWithTest1 = studentTest1Query.GroupBy(a => a.Student).Where(a => a.Select(b => b.TestLevel.ProficiencyId).Contains((int)LookUpEnum.LookUpEnum.TestLevelProficiency.NotProficient) 
                                    && !a.Select(b => b.TestLevel.ProficiencyId).Contains((int)LookUpEnum.LookUpEnum.TestLevelProficiency.Proficient)); 

     // get the count of students whos attended less than 30 days of services 
     count1 = groupedStudentWithTest1.Where(a => a.Key.StudentServices.Where(b => b.Date >= serviceDateFrom && b.Date <= serviceDateTo).GroupBy(b => b.Date).Count() < 30).Count(); 

     // test 2 query 
     IQueryable<StudentTestDm> studentTest2Query = studentTestQuery; 

     if (studentAcademicTestProficiencyGrowthParameter.Test2SchoolYear.HasValue) 
     { 
      studentTest2Query = studentTest2Query.Where(a => a.Year == studentAcademicTestProficiencyGrowthParameter.Test2SchoolYear); 
     } 

     if (studentAcademicTestProficiencyGrowthParameter.Test2TestDate.HasValue) 
     { 
      studentTest2Query = studentTest2Query.Where(a => a.TestDate == studentAcademicTestProficiencyGrowthParameter.Test2TestDate); 
     } 

     // we are grabbing the students who are not-proficient in test 1 but are proficient in test 2 
     IQueryable<IGrouping<StudentDm, StudentTestDm>> groupedStudentWithImprovedTest2 = studentTest2Query.GroupBy(a => a.Student).Where(a => a.Select(b => b.TestLevel.ProficiencyId).Contains((int)LookUpEnum.LookUpEnum.TestLevelProficiency.Proficient)) 
                                    .Where(a => groupedStudentWithTest1.Select(b => b.Key.Id).Contains(a.Key.Id)); 

     // THIS QUERY TIMES OUT (ON Database Server): get the count students who attended less than 30 days of services 
     count2 = groupedStudentWithImprovedTest2.Where(a => a.Key.StudentServices.Where(b => b.Date >= serviceDateFrom && b.Date <= serviceDateTo).GroupBy(b => b.Date).Count() < 30).Count(); 
+0

檢查與服務器的連接是否正確與數據庫 – Prabu

+1

@Prabu該評論沒有任何意義。請解釋_「適合您的數據庫」_的含義。 – CodeCaster

+1

那麼你的期望是什麼?有人不知道你的代碼或數據庫或環境,並提出解決方案? – nvoigt

回答

1

查看聊天討論。查詢遵循'可選過濾'模式,問題是參數嗅探。

該查詢是從SQL事件探查器中捕獲並在SSMS中運行的,但無法複製該問題。

然而,當也從SQL事件探查器中加入上述所有SET選項,問題在SSMS

添加OPTION (RECOMPILE)到查詢結束轉載似乎解決問題。

此鏈接EF 6 Parameter Sniffing顯示了一種方法通過LINQ添加OPTION (RECOMPILE)(具體而言這是在sp_executesql關閉的引號之前添加)。我會等待原始海報的反應,以確定這是否真的有效。

鏈接說「這是可以使用EF6的攔截功能」

,並顯示一些像這樣的代碼(有刪節):

public class OptionRecompileHintDbCommandInterceptor : IDbCommandInterceptor 
{ 


    public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext) 
    { 
     addQueryHint(command); 
    } 

    public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext) 
    { 
     addQueryHint(command); 
    } 

    private static void addQueryHint(IDbCommand command) 
    { 
     if (command.CommandType != CommandType.Text || !(command is SqlCommand)) 
      return; 

     if (command.CommandText.StartsWith("select", StringComparison.OrdinalIgnoreCase) && !command.CommandText.Contains("option(recompile)")) 
     { 
      command.CommandText = command.CommandText + " option(recompile)"; 
     } 
    } 
} 
相關問題