我有一个非平凡的Linq To Sql查询,我试图将其分解为可读性/进一步过滤/重用。
重构的代码如下所示,其中 ids 是为抓取ID而执行的子查询。
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;
'ids'是IOrderedQueryable< csExtendedQAIncident_Docs>它本身有许多标准和嵌套子查询(即包含在SQL服务器上被转换为EXISTS样式查询的包含)
无论如何,这里的问题是,当上面的结果查询中包含完整的子查询时,查询可以正常运行。
当查询被提取到它自己的变量中时,查询在运行时死于SqlFactory.Member的NullReferenceException(下面的部分堆栈跟踪)
System.NullReferenceException:未将对象引用设置为对象的实例。 在System.Data.Linq.SqlClient.SqlFactory.Member(SqlExpression expr,MemberInfo成员) 在System.Data.Linq.SqlClient.QueryConverter.VisitMemberAccess(MemberExpression ma) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) 在System.Data.Linq.SqlClient.QueryConverter.Visit(表达式节点) 在System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) 在System.Data.Linq.SqlClient.QueryConverter.VisitMethodCall(MethodCallExpression mc) at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node) 在System.Data.Linq.SqlClient.QueryConverter.Visit(表达式节点) 在System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp) 在
我怀疑这是Linq到Sql的查询评估过程中的一个错误 - 但是想知道是否有其他人可能遇到过这样的问题?
我进入了框架源代码 - 但当然问题是,虽然我可以找到异常的确切源代码行,但我正在使用的Linq程序集已经过优化,我无法检查变量等等。
注意:请记住,这个查询,尽管有点长,但实际上并不是SPROC在此场景中的一个很好的选择(特别是因为我们在这里遇到了SQL 2000并且无法参数化TOP :()< / p>
修改:找到另一个对未解决的非常类似问题的引用http://www.eggheadcafe.com/software/aspnet/31934404/linq-combined-query.aspx
Edit2 :问问你们会收到; 0我想我会把id子查询保留在这里,因为我认为它实际上并不相关(并且提到它很复杂等)。请不要责怪我的废话db设计 - 但是知道我在SQL上为这个查询工作了一点以获得可接受的性能,然后翻译成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;