NHibernate Linq cannot call a regular method that returns an IQueryable<T>
I have the following query:
public ICollection<AccountAbsence> GetAccountAbsencesByRosters(WorkRoster[] workRosters)
{
var processedWorkRosters = from workRoster in workRosters
select new WorkRoster
{
Start = DateUtil.SyncToCrmTime(workRoster.Start),
End = DateUtil.SyncToCrmTime(workRoster.End),
ServicePlan = workRoster.ServicePlan
};
return (from absence in GetNonCanceledAbsencesCriteria()
where processedWorkRosters.Any(workRoster => workRoster.ServicePlan.Account.Id == absence.Account.Id && ((absence.End.HasValue && absence.End > workRoster.Start && absence.Start < workRoster.End) || (!absence.End.HasValue && absence.Start <= workRoster.End)))
select absence).ToList();
}
private IQueryable<AccountAbsence> GetNonCanceledAbsencesCriteria()
{
return ActiveRecordLinq.AsQueryable<AccountAbsence>().AsQueryable()
.Where(absence => absence.CancelDate == null || absence.CancelReason == null);
}
And for some reason GetNonCanceledAbsencesCriteria() cannot be evaluated.
Here's the exception I am getting:Message: Specified method is not supported.
Stack Trace: at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector开发者_StackOverflow社区.GetClassName(IASTNode querySource)
at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.Process(IASTNode tree)
at NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process()
at NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process(IASTNode ast
ISessionFactoryImplementor factory)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast
String queryIdentifier
String collectionRole
Boolean shallow
IDictionary`2 filters
ISessionFactoryImplementor factory)
at NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(String queryIdentifier
IQueryExpression queryExpression
String collectionRole
Boolean shallow
IDictionary`2 filters
ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.HQLExpressionQueryPlan.CreateTranslators(String expressionStr
IQueryExpression queryExpression
String collectionRole
Boolean shallow
IDictionary`2 enabledFilters
ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr
IQueryExpression queryExpression
String collectionRole
Boolean shallow
IDictionary`2 enabledFilters
ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr
IQueryExpression queryExpression
Boolean shallow
IDictionary`2 enabledFilters
ISessionFactoryImplementor factory)
at NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression
Boolean shallow
IDictionary`2 enabledFilters)
at NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression
Boolean shallow)
at NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression)
at NHibernate.Linq.NhQueryProvider.PrepareQuery(Expression expression
IQuery& query
NhLinqExpression& nhQuery)
at NHibernate.Linq.NhQueryProvider.Execute(Expression expression)
at NHibernate.Linq.NhQueryProvider.Execute[TResult](Expression expression)
at Remotion.Data.Linq.QueryableBase`1.GetEnumerator()
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Danel.Nursing.Scheduling.Actions.DataServices.AccountAbsenceDataService.GetAccountAbsencesByRosters(WorkRoster[] workRosters) in D:\Work\DanelNursing\branches\AugustVersion\Scheduling\Danel.Nursing.Scheduling.Actions\DataServices\AccountAbsenceDataService.cs:line 102
at Danel.Nursing.Scheduling.Actions.Validators.AccountAbsenceWorkRostersValidator.GetFailedWorkRosters() in D:\Work\DanelNursing\branches\AugustVersion\Scheduling\Danel.Nursing.Scheduling.Actions\Validators\AccountAbsenceWorkRostersValidator.cs:line 50
at Danel.Nursing.Scheduling.Actions.Generators.WorkingJournalsDataGenerator.generateLists(Branch branch
Int32 month
Int32 year) in D:\Work\DanelNursing\branches\AugustVersion\Scheduling\Danel.Nursing.Scheduling.Actions\Generators\WorkingJournalsDataGenerator.cs:line 412
at Danel.Nursing.Scheduling.Actions.Generators.WorkingJournalsDataGenerator.Generate(Branch branch
Int32 month
Int32 year) in D:\Work\DanelNursing\branches\AugustVersion\Scheduling\Danel.Nursing.Scheduling.Actions\Generators\WorkingJournalsDataGenerator.cs:line 108
at Danel.Nursing.Scheduling.Controllers.WorkingJournalsController.<>c__DisplayClass37.<ShowWorkingJournalsData>b__32() in D:\Work\DanelNursing\branches\AugustVersion\Scheduling\Danel.Nursing.Scheduling\Controllers\WorkingJournalsController.cs:line 826
at Danel.Nursing.Scheduling.Viewlets.WaitForAction.Worker_DoWork(Object sender
DoWorkEventArgs e) in D:\Work\DanelNursing\branches\AugustVersion\Scheduling\Danel.Nursing.Scheduling\Viewlets\WaitForAction.cs:line 40
It seems like the LINQ provider should be able to figure this out.
Am I missing something here or is it not implemented? EDIT: It seems I was wrong and that processedWorkRosters.Any() cannot be evaluated. How am I supposed to compare with an external array than?The method GetNonCanceledAbsencesCriteria()
returns an IQueryable, which conmes from the NH provider, which means any operation you perform on it is more than highly likely to get interpreted into SQL speak.
from absence in GetNonCanceledAbsencesCriteria()
where processedWorkRosters.Any( ... )
select absence
The problem with the above is that processedWorkRosters
is a variable foreign to the NH Linq provider, which means it doesn't know how to translate them into sql speak.
Try:
from absence in GetNonCanceledAbsencesCriteria().ToArray()
where processedWorkRosters.Any( ... )
select absence
The ToArray()
forces the GetNonCanceledAbsencesCriteria()
to be evaluated immediately, but may be suboptimal (or not) ... and if is you may need to re-write the where clause to "close-to" SQL speak.
精彩评论