开发者

NHibernate Linq cannot call a regular method that returns an IQueryable<T>

开发者 https://www.devze.com 2023-03-27 07:29 出处:网络
I have the following query: public ICollection<AccountAbsence> GetAccountAbsencesByRosters(WorkRoster[] workRosters)

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消