SQL语句的某些部分嵌套得太深。重写查询或将其分解为较小的查询

时间:2013-01-05 19:45:50

标签: asp.net asp.net-mvc entity-framework linq-to-entities

我的asp.net mvc web应用程序中有folloiwng方法,我使用Entity框架作为数据访问层: -

        public IEnumerable<AaaUserContactInfo> getcontactinfo(long[] id)
        {
var organizationsiteids = (from accountsitemapping in entities.AccountSiteMappings
where id.Any(accountid => accountsitemapping.ACCOUNTID == accountid)
select accountsitemapping.SITEID).ToList();

var usersdepts = from userdept in entities.UserDepartments
join deptdefinition in entities.DepartmentDefinitions on userdept.DEPTID equals deptdefinition.DEPTID

where organizationsiteids.Any(accountid => deptdefinition.SITEID == accountid)

var contactsinfos = from contactinfo in entities.AaaUserContactInfoes 
                                join userdept in usersdepts on  contactinfo.USER_ID equals userdept.USERID

                                 select contactinfo;

            return contactsinfos;

但如果记录数量巨大,那么我将得到以下错误: -

  

SQL语句的某些部分嵌套太深。重写了   查询或将其分解为较小的查询。描述:未处理   在执行当前Web请求期间发生异常。   请查看堆栈跟踪以获取有关错误的更多信息   它起源于代码。

     

异常详细信息:System.Data.SqlClient.SqlException:部分内容   你的SQL语句嵌套得太深了。重写查询或破解它   进入较小的查询。

     

来源错误:

     

执行期间生成了未处理的异常   当前的网络请求。有关的来源和位置的信息   可以使用下面的异常堆栈跟踪来识别异常。

     

堆栈追踪:

     

[SqlException(0x80131904):SQL语句的某些部分是嵌套的   太深了重写查询或将其分解为较小的查询。]   System.Data.SqlClient.SqlConnection.OnError(SqlException异常,   Boolean breakConnection,Action 1 wrapCloseInAction) +388
System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +688
System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +4403
System.Data.SqlClient.SqlDataReader.TryConsumeMetaData() +82
System.Data.SqlClient.SqlDataReader.get_MetaData() +135
System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) +6665229
System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async, Int32 timeout, Task& task, Boolean asyncWrite) +6667096
System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, TaskCompletionSource
1完成,Int32超时,Task&amp;任务,   Boolean asyncWrite)+577
  System.Data.SqlClient.SqlCommand.RunExecuteReader(的CommandBehavior   cmdBehavior,RunBehavior runBehavior,Boolean returnStream,String   方法)+107
  System.Data.SqlClient.SqlCommand.ExecuteReader(的CommandBehavior   行为,字符串方法)+288
  System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(的CommandBehavior   行为)+180
  System.Data.EntityClient.EntityCommandDefinition.ExecuteStoreCommands(EntityCommand   entityCommand,CommandBehavior行为)+689

如果返回的记录数量很少,那么代码可以正常工作,那么问题可能是什么呢?

3 个答案:

答案 0 :(得分:3)

根据评论中上面提到的重复问题的答案,尝试以下作为第一个查询的where子句,因为最有可能是那个给出所有麻烦的那个:

where id.Contains(accountsitemapping.ACCOUNTID)

答案 1 :(得分:1)

我很想删掉那里的所有联接并单独进行查找。

这样做可能会产生反效果,但如果你

var organizationsiteids = (from accountsitemapping in entities.AccountSiteMappings
where id.Any(accountid => accountsitemapping.ACCOUNTID == accountid)
select accountsitemapping.SITEID).ToList();

然后将其保留在内存中,循环遍历该集合并使用它从数据库中获取其余的详细信息,它将简化查询,并可能解决错误。

然而,作为对实际问题的回答,最有可能生成的SQL是在幕后生成SQL连接,这些连接必须有许多连接条件,或者是SQL服务器要处理的嵌套查询。

你可以做两件事来帮助解决这个问题。

1)如果您有权访问正在使用的SQL服务器,请使用SQL Server Profiler工具,并查看正在生成的SQL代码。或者2)(我不记得如何做到这一点)但是获得EF / L2S或者你用什么来将SQL输出到visual studio中的调试/输出窗口。

您可能想做的最后一件事。

下载LinqPad(http://www.linqpad.net/)并使用它在您的代码中重现查询,然后您可以坐在沙盒中使用Linq语句,以帮助您了解正在发生的事情

除非你能发布正在生成的SQL(选项1是首选方式),而且我现在正在网上登录,所以除此之外我不能提供更多的帮助: - )

答案 2 :(得分:0)

另一个解决方案是迭代记录获取另一个并聚合到最终列表。

这不是最快,不是美,而是会解决。