NHibernate Linq не может вызвать обычный метод, который возвращает IQueryable <T> - PullRequest
2 голосов
/ 09 августа 2011

У меня есть следующий запрос:

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);
    }

И по какой-то причине GetNonCanceledAbsencesCriteria () не может быть оценена.
Вот исключение, которое я получаю:

Message: Specified method is not supported.
Stack Trace:    at NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.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

Кажетсякак поставщик LINQ должен быть в состоянии понять это.
Я что-то здесь упускаю или это не реализовано?РЕДАКТИРОВАТЬ:
Кажется, я был не прав, и обработанныйWorkRosters.Any () не может быть оценена.
Как я должен сравнивать с внешним массивом, чем?

1 Ответ

3 голосов
/ 14 августа 2011

Метод GetNonCanceledAbsencesCriteria() возвращает IQueryable, который получен от поставщика NH, что означает, что любая операция, которую вы выполняете над ним, с большей вероятностью будет интерпретирована в языке SQL.

from absence in GetNonCanceledAbsencesCriteria()
where processedWorkRosters.Any( ... )
select absence

Проблема с вышесказанным заключается в том, что processedWorkRosters - это переменная, чуждая провайдеру NH Linq, а это значит, что он не знает, как перевести их в SQL.

Попробуйте:

from absence in GetNonCanceledAbsencesCriteria().ToArray()
where processedWorkRosters.Any( ... )
select absence

ToArray() заставляет GetNonCanceledAbsencesCriteria() быть оцененным немедленно, но может быть неоптимальным (или нет) ... и, если это так, вам может понадобиться переписать выражение where для "близкого к" языка SQL.

...