0

我对“分组依据”有疑问。在迁移到 Orchard 1.5.1 之前,我对这段代码没有任何问题:

var list = (from r in GetAll()
                    group new { r.FormulaCatId, r.InputPeriodId, r.CurrencyId } by new { r.FormulaCatId, r.InputPeriodId, r.CurrencyId }
                        into grp
                        select (new CatCurPerViewModel
                        {
                            FormulaCatId = grp.Key.FormulaCatId,
                            InputPeriodId = grp.Key.InputPeriodId,
                            CurrencyId = grp.Key.CurrencyId
                        }));

但是在迁移到 Orchard 1.6 后出现了这个问题:

2013-01-10 15:01:25,704 [7] Orchard.Exceptions.DefaultExceptionPolicy - An unexpected exception was caught
System.NotImplementedException: The method or operation is not implemented.
at NHibernate.Linq.CacheableExpressionNode.Resolve(ParameterExpression inputParameter, Expression   expressionToBeResolved, ClauseGenerationContext clauseGenerationContext)
at Remotion.Linq.Parsing.Structure.IntermediateModel.ExpressionResolver.GetResolvedExpression(Expression unresolvedExpression, ParameterExpression parameterToBeResolved, ClauseGenerationContext clauseGenerationContext)
at Remotion.Linq.Parsing.Structure.IntermediateModel.GroupByExpressionNode.<>c__DisplayClass1.<GetResolvedKeySelector>b__0(ExpressionResolver r)
at Remotion.Linq.Parsing.Structure.IntermediateModel.ResolvedExpressionCache`1.GetOrCreate(Func`2 generator)
at Remotion.Linq.Parsing.Structure.IntermediateModel.GroupByExpressionNode.CreateResultOperator(ClauseGenerationContext clauseGenerationContext)
at Remotion.Linq.Parsing.Structure.IntermediateModel.ResultOperatorExpressionNodeBase.ApplyNodeSpecificSemantics(QueryModel queryModel, ClauseGenerationContext clauseGenerationContext)
at Remotion.Linq.Parsing.Structure.IntermediateModel.MethodCallExpressionNodeBase.Apply(QueryModel queryModel, ClauseGenerationContext clauseGenerationContext)
at Remotion.Linq.Parsing.Structure.QueryParser.ApplyAllNodes(IExpressionNode node, ClauseGenerationContext clauseGenerationContext)
at Remotion.Linq.Parsing.Structure.QueryParser.GetParsedQuery(Expression expressionTreeRoot)
at NHibernate.Linq.NhLinqExpression.Translate(ISessionFactoryImplementor sessionFactory)
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.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.Execute(Expression expression)
at NHibernate.Linq.DefaultQueryProvider.Execute[TResult](Expression expression)
at Remotion.Linq.QueryableBase`1.GetEnumerator()
at System.Linq.Buffer`1..ctor(IEnumerable`1 source)
at System.Linq.Enumerable.ToArray[TSource](IEnumerable`1 source)
at SAS.Core.Services.RateService.ListCatCurPer()
at SAS.Core.Controllers.RatesAdminController.Index()
at lambda_method(Closure , ControllerBase , Object[] )
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClass13.<InvokeActionMethodWithFilters>b__10()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
4

1 回答 1

2

出现问题是因为在 orchard 1.6 中 Orchard.Data.Repository<T> 的 Table 属性以下列方式实现:

    public virtual IQueryable<T> Table
    {
        get { return Session.Query<T>().Cacheable(); }
    }

并且您不能将 Group By 与 Cacheable() 一起使用 - HNIbernate Jira 中有一张公开票

Orchard 调用 Cacheable() 是为了利用二级 Nhibernate 缓存

如果你不使用也不打算使用这个二级缓存和Orchard中的相应模块,你可以下载Orchard源码,将Orchard.Data.Repository<T>中Table属性的实现修改为

    public virtual IQueryable<T> Table
    {
        get { return Session.Query<T>(); }
    }

这将解决您的问题。

或者,如果您不想更改 Orchard 源,您可以创建自己的通用存储库类,并将其连接到 DependencyContainer(默认情况下,Orchard 带有 Autofac)。以下是使用 Autofac 2.6.3.862 的方法:

public class MyRepository<T> : Orchard.Data.Repository<T> where T:class
{
    public MyRepository(ISessionLocator sessionLocator) : base(sessionLocator)
    {
    }

    public override System.Linq.IQueryable<T> Table
    {
        get { return Session.Query<T>(); }
    }
}

public class MyDataModule : Autofac.Module
{
    protected override void AttachToComponentRegistration(Autofac.Core.IComponentRegistry componentRegistry, Autofac.Core.IComponentRegistration registration)
    {
        base.AttachToComponentRegistration(componentRegistry, registration);

        Type limitType = registration.Activator.LimitType;
        if (!limitType.IsGenericType || limitType.GetGenericTypeDefinition() != typeof (Repository<>)) return;

        var epamRepoTye = typeof(MyRepository<>).MakeGenericType(limitType.GetGenericArguments());

        registration.Activating += (s, e) =>
                                       {
                                           var locator = e.Context.Resolve<ISessionLocator>();
                                           e.Instance = Activator.CreateInstance(epamRepoTye, new object[] {locator});
                                       };
    }
}

如果您可以保证包含它的程序集将在 Orchard.Core 程序集之后加载,则可能(我尚未对此进行测试) MyDataModule 类可以简化:

public class MyDataModule : Autofac.Module
{
    protected override void Load(ContainerBuilder builder)
    {
        builder.RegisterGeneric(typeof(MyRepository<>)).As(typeof(IRepository<>)).InstancePerDependency();
    }
}
于 2013-05-17T14:49:10.020 回答