【问题标题】:NHibernate Specified method is not supported不支持 NHibernate 指定的方法
【发布时间】:2015-12-26 10:38:45
【问题描述】:

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

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

`NHibernate System.NotSupportedException 不支持指定的方法。 {Name = "PolymorphicQuerySourceDetector" FullName = "NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector"} 在 NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.GetClassName(IASTNode querySource) 在 NHibernate.Hql.Ast.ANTLR.PolymorphicQuerySourceDetector.Process(IASTNode 树) 在 NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process() 在 NHibernate.Hql.Ast.ANTLR.AstPolymorphicProcessor.Process(IASTNode ast,ISessionFactoryImplementor 工厂) 在 NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(IASTNode ast,String queryIdentifier,String collectionRole,Boolean shallow,IDictionary`2 过滤器,ISessionFactoryImplementor factory) 在 NHibernate.Hql.Ast.ANTLR.ASTQueryTranslatorFactory.CreateQueryTranslators(字符串 queryIdentifier,IQueryExpression queryExpression,字符串 collectionRole,布尔浅层,IDictionary`2 过滤器,ISessionFactoryImplementor 工厂) 在 NHibernate.Engine.Query.HQLExpressionQueryPlan.CreateTranslators(字符串表达式Str,IQueryExpression queryExpression,字符串 collectionRole,布尔浅层,IDictionary`2 enabledFilters,ISessionFactoryImplementor 工厂) 在 NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(字符串表达式Str,IQueryExpression queryExpression,字符串 collectionRole,布尔浅层,IDictionary`2 enabledFilters,ISessionFactoryImplementor 工厂) 在 NHibernate.Engine.Query.HQLExpressionQueryPlan..ctor(String expressionStr, IQueryExpression queryExpression, Boolean shallow, IDictionary`2 enabledFilters, ISessionFactoryImplementor factory) 在 NHibernate.Engine.Query.QueryPlanCache.GetHQLQueryPlan(IQueryExpression queryExpression,布尔浅,IDictionary`2 enabledFilters) 在 NHibernate.Impl.AbstractSessionImpl.GetHQLQueryPlan(IQueryExpression queryExpression, Boolean shallow) 在 NHibernate.Impl.AbstractSessionImpl.CreateQuery(IQueryExpression queryExpression) 在 NHibernate.Linq.DefaultQueryProvider.PrepareQuery(表达式表达式,IQuery& 查询,NhLinqExpression& nhQuery) 在 NHibernate.Linq.DefaultQueryProvider.Execute(表达式表达式) 在 NHibernate.Linq.DefaultQueryProvider.Execute[TResult](表达式表达式) 在 Remotion.Linq.QueryableBase`1.GetEnumerator() 在 System.Collections.Generic.List`1..ctor(IEnumerable`1 集合) 在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 源) 在 EzLife.Tasks.EmployeeCudTasks.GetEmployees(List`1 listSkill,List`1 listDepartment,List`1 listAssignment,String searchTerm,String jobtitle,String tier,String 能力,Nullable`1 startDate,Nullable`1 endDate,Int32 努力,Nullable `1 活动,Int32 currentPage,Int32 pageSize,Int32 sortId,Int32 sortName,Int32 sortTitle,Int32 sortTier,Int32 sortJoinedDate,Int32 sortDepartment)在 d:\Projects\EzLife\_source\Ezlife\app\EzLife.Tasks\EmployeeCudTasks.cs:第 206 行`

这是我的代码

`public static IQueryable GetEmployeesQ(this IQueryable employees, IQueryable employeeTitles, int currentPage,int pageSize) { var query = 来自员工中的员工 在employeeTitle 中加入employeeTitle 在employee.Id 上等于employeeTitle.Employee.Id 选择新的 EmployeeDto() { Id = 员工.Id, CustomCode = 员工.CustomCode, 名字 = 雇员。名字, 姓氏 = 雇员。姓氏, MiddleName = 雇员.MiddleName, 全名 = string.Empty, JoinedDate = 员工.JoinedDate, }; 返回查询; }

public static IQueryable GetEmployeeTitlesQ(this IQueryable employeeTitles) { 从employeeTitles中的et1返回 加入et2 ( 来自雇员头衔中的 et orderby et.Employee.Id, et.StartDate 通过 et.Employee.Id 将 et 分组到 etmax 选择新 { Id = etmax.Max(et => et.Id) } ) 在 et1.Id 上等于 et2.Id 选择 et1; }`

我在 GetEmployeesQ 中将 GetEmployeeTitlesQ 称为: ' 公共 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() 函数有问题,但我不知道为什么。 有什么办法可以解决吗?

【问题讨论】:

  • ID 的数据类型是什么?
  • 尝试一次调试一个查询来得到确切的问题。用当前的代码,很难预测。
  • 是的,我做到了@Nikita,当我只使用查询时,没关系并返回正确的数据。
  • 如果你尝试etmax.Select(et =&gt; et.Id).Max()会怎样?

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


【解决方案1】:

NHibernate 无法将每个 LINQ 查询转换为 SQL。对我来说,重新排列我的 wherejoin 语句的顺序就足够了。

【讨论】:

  • 这不是答案,而是评论。另外,通过阅读此评论,可以得出结论,NHibernate 不是一个严肃的解决方案,因为它不清楚它能做什么或不能做什么;此外,以不同的语法编写相同的指令可以使其工作或不工作。对吗?
【解决方案2】:

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

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。

上述情况的副作用是您将无法将整个选择作为对数据库的 SQL 查询来执行。

底线(至少对我而言)是您应该仔细排序 NHibernate 层中所有与数据库相关的操作,当查询完成后,将其转换为可枚举的,以防止潜在的进一步 LINQ 操作从业务逻辑调用到干扰IQueryable 的内部细节。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多