不支持NHibernate指定的方法

时间:2015-09-29 04:25:23

标签: c# .net linq nhibernate fluent-nhibernate

我使用S#arpLite开发webapp来构建查询从许多表中获取列表。 使用NHibernate版本3.3.1.4000

我在应用程序运行时遇到错误,例如

 `NHibernate System.NotSupportedException Specified method is not supported. {Name = "PolymorphicQuerySourceDetector" FullName = "NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector"}

   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.DefaultQueryProvider.PrepareQuery(Expression expression, IQuery& query, NhLinqExpression& nhQuery)
   at NHibernate.Linq.DefaultQueryProvider.Execute(Expression expression)
   at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
   at Remotion.Linq.QueryableBase`1.GetEnumerator()
   at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
   at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
   at EzLife.Tasks.EmployeeCudTasks.GetEmployees(List`1 listSkill, List`1 listDepartment, List`1 listAssignment, String searchTerm, String jobtitle, String tier, String competency, Nullable`1 startDate, Nullable`1 endDate, Int32 effort, Nullable`1 active, Int32 currentPage, Int32 pageSize, Int32 sortId, Int32 sortName, Int32 sortTitle, Int32 sortTier, Int32 sortJoinedDate, Int32 sortDepartment) in d:\Projects\EzLife\_source\Ezlife\app\EzLife.Tasks\EmployeeCudTasks.cs:line 206`

这是我的代码

 `public static IQueryable GetEmployeesQ(this IQueryable employees, IQueryable employeeTitles, int currentPage,int pageSize)
        {
           var query = from employee in employees
                        join employeeTitle in employeeTitles
                        on employee.Id equals employeeTitle.Employee.Id
                        select new EmployeeDto()
                        {
                            Id = employee.Id,
                            CustomCode = employee.CustomCode,
                            FirstName = employee.FirstName,
                            LastName = employee.LastName,
                            MiddleName = employee.MiddleName,
                            FullName = string.Empty,
                            JoinedDate = employee.JoinedDate,
                        };
            return query;
        }

public static IQueryable GetEmployeeTitlesQ(this IQueryable employeeTitles) { return from et1 in employeeTitles join et2 in ( from et in employeeTitles orderby et.Employee.Id, et.StartDate group et by et.Employee.Id into etmax select new { Id = etmax.Max(et => et.Id) } ) on et1.Id equals et2.Id select et1; }`

I call GetEmployeeTitlesQ in GetEmployeesQ as : ' public IList GetEmployees(int currentPage = 1, int pageSize = 20) {

IList<EmployeeDto> employees = new List<EmployeeDto>(); IQueryable<EmployeeTitle> employeeTitles = employeeTitleRep.GetAll().GetEmployeeTitlesQ(); IQueryable<EmployeeDto> employeeDto = employeeRep.GetAll().GetEmployeesQ( employeeTitles , jobTitles , currentPage , pageSize); try { employees = employeeDto.ToList(); } catch (Exception ex) { var mess = ex.Message.ToString(); } return employees; }

” 我猜Max()函数存在问题,但我不知道为什么。 有什么方法可以解决它吗?

2 个答案:

答案 0 :(得分:5)

NHibernate无法将每个LINQ查询转换为SQL。对我而言,只需重新排列wherejoin语句的顺序即可。

答案 1 :(得分:-1)

我建议您在代码中进行以下更改,这有助于我克服同样的异常:

public static IQueryable GetEmployeeTitlesQ(this IQueryable employeeTitles)
{
    var employeeTitlesEnumerable = employeeTitles.ToArray();
    return from et1 in employeeTitlesEnumerable 
           join et2 in (
               from et in employeeTitlesEnumerable 
               orderby et.Employee.Id, et.StartDate
               group et by et.Employee.Id into etmax
               select new { Id = etmax.Max(et => et.Id) }
           ) on et1.Id equals et2.Id
           select et1;
}

我在可查询上添加了对.ToArray()的调用。我对FluentNHibernate的体验是,有时返回的IQueryable试图将整个LINQ表达式转换为SQL。当查询涉及无法表示为SQL的对象时,将会抛出您看到的错误。所以,我在这里的猜测是,Max调用不被认为是NHibernate可以正确翻译的东西。

使用.ToArray()(或者如果您更喜欢.ToList())将NHibernate可查询转换为IEnumerable的实例,然后完全由.NET框架处理。这意味着应用于IEnumerable的LINQ表达式将不再转换为SQL。

上述的副作用是,您将无法将整个select作为针对数据库的SQL查询执行。

底线(至少对我来说)是你应该在NHibernate层内仔细地命令所有与数据库相关的操作,并且在查询完成后,将其转换为可枚举,以防止可能的进一步LINQ操作从业务逻辑调用到干扰IQueryable的内部细节。