Linq To Sql - Refactoring Complex Queries Into Smaller Parts throws NullReferenceException
I have a non-trivial Linq To Sql query that I'm trying to break down into pieces for the sake of readability / further filtering / reuse.
The refactored code looks like this, where ids is the subquery performed to grab the ids.
var results = from solution in context.csExtendedQAIncident_Docs
join solutionText in context.csNTexts
on solution.chIdNo equals solutionText.chIdNo
where solutionText.chColumnId == "Solution"
//this is a very complicated subquery that returns a short list of the ids we need
&& (ids).Select(s => s.chIdNo)
//the TOP query portion - applied to just the ids
.Take(count ?? Settings.Current.WCFServices().Output.HomePage.MaxRows)
.Contains(solution.chIdNo)
select solution;
The 'ids' is an IOrderedQueryable<csExtendedQAIncident_Docs> which itself has a number of criteria and nested subqueries (i.e. Contains which gets translated into EXISTS style queries on SQL server)
In any event, the issue here is that when the full-blown subquery is included in the results query above, the query works without a hitch.
When the query is pulled out into it's own variable, the query dies at runtime with a NullReferenceException at SqlFactory.Member (partial stack trace below)
System.Nu开发者_运维问答llReferenceException: Object reference not set to an instance of an object. at System.Data.Linq.SqlClient.SqlFactory.Member(SqlExpression expr, MemberInfo member) at System.Data.Linq.SqlClient.QueryConverter.VisitMemberAccess(MemberExpression ma) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node) at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) at System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) at System.Data.Linq.SqlClient.QueryConverter.Visit(Expression node) at System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) at
I suspect this is a bug in Linq to Sql's query evaluation process -- but was wondering if anyone else might have come across such an issue?
I stepped into the Framework source code -- but of course the trouble with that is that while I can hit the exact source line of the exception, the Linq assembly I'm using has been optimized and I can't inspect variables, etc.
Note: Keep in mind that this query, despite being a little long is actually not a great candidate in this scenario for a SPROC (especially since we're stuck on SQL 2000 here and can't parameterize TOP :( )
Edit: Found one other reference to a very similar issue out there that was never resolved http://www.eggheadcafe.com/software/aspnet/31934404/linq-combined-query.aspx
Edit2: Ask and ye shall receive ;0 I figured I would keep the id subquery out of here because I don't think its actually relevant (and as mentioned its complicated, etc). Please don't blame the crap db design on me -- but know that I worked on the SQL for this query for a bit to get acceptable performance, and then translated to Linq To Sql.
var ids = from solutionIds in context.csExtendedQAIncident_Docs
where solutionIds.iIncidentTypeId == 102094
&& solutionIds.tiRecordStatus == 1
&& solutionIds.iLanguage == 102074
&& null != solutionIds.chIdNo
&& (from openTo in context.csOpenTos
where onyxIdentity.GetDocumentAccessLevels().Union(new[] { "BUSG5" }).ToArray().Contains(openTo.vchOpenTo)
select openTo.chIdNo
).Distinct().Contains(solutionIds.chIdNo)
&& (from solutionProductAssocation in context.csProductDocs
where (from allowedProduct in context.KB_User_Allowed_Products
where allowedProduct.UserId == userId
select allowedProduct.ModelCode
).Contains(solutionProductAssocation.chModelCd)
select solutionProductAssocation.chIdNo).Distinct().Contains(solutionIds.chIdNo)
orderby solutionIds.dtUpdateDate descending
select solutionIds;
精彩评论