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

Cacheable() で Group By を使用することはできません - HNIbernate Jira にオープン チケットがあります

Orchard は、第 2 レベルの Nhibernate キャッシュを利用するためにCacheable() 呼び出しを行います。

この第 2 レベルのキャッシュと 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});
                                       };
    }
}

おそらく (私はこれをテストしていません) MyDataModule クラスは、それを含むアセンブリが Orchard.Core アセンブリよりも後で読み込まれることを保証できれば、単純化できます。

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 に答える