2

私はエンティティを持っています:

public class SalesUnit
{
    public virtual long Id { get; set; }
    public virtual string Name { get; set; }

}

関連する Dto:

public class SalesUnitDto
{
    public long Id { get; set; }
    public string Name { get; set; }

}

私は非常に単純なクエリを持っています:

SalesUnitDto result = null; 
var list = _session.QueryOver<SalesUnit>()
                .SelectList(l => l
                    .Select(x => x.Id).WithAlias(() => result.Id)
                    .Select(x => x.Name).WithAlias(() => result.Name))
                .TransformUsing(Transformers.AliasToBean<SalesUnitDto>())
                //.Cacheable()
                .List<SalesUnitDto>();

二次キャッシュを接続するまでは機能していました。したがって、Cacheable()行のコメントを外すと、例外が発生します。

メッセージ: 値を null にすることはできません。パラメータ名: エイリアス StackTrace:

   at NHibernate.Transform.AliasedTupleSubsetResultTransformer.IncludeInTransform(String[] aliases, Int32 tupleLength)
   at NHibernate.Transform.CacheableResultTransformer.Create(ITupleSubsetResultTransformer transformer, String[] aliases, Boolean[] includeInTuple)
   at NHibernate.Loader.Loader.GenerateQueryKey(ISessionImplementor session, QueryParameters queryParameters)
   at NHibernate.Loader.Loader.ListUsingQueryCache(ISessionImplementor session, QueryParameters queryParameters, ISet`1 querySpaces, IType[] resultTypes)
   at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results)

それで、それの何が問題なのですか?NHibernate のバグですか?さまざまなプロバイダーを試しましたが、役に立ちませんでした。また、次のように CacheableResultTransformer を作成しようとしました:

CacheableResultTransformer.Create(Transformers.AliasToBean<SalesUnitDto>(), new[] { "Id", "Name" }, new[] { true, true })

データを返してキャッシュできますが、タプル (object[]) としてのみです。Dtoを返すことができませんでした。

問題を示す実際の例を次に示します: github

4

2 に答える 2

2

(N)Hibernate のバグ/制限であることが判明しました。キャッシュがアクティブになると、元の引数は実装に不可欠な引数をIResultTransformer受け取り始めるため、例外が発生します。 null string[] aliasesAliasToBeanTransformer

回避策として、次のカスタム拡張メソッドとトランスフォーマーを提案できます。これは、呼び出されたときに現在のエイリアスを保存しAliasToBeanTransformer、渡された引数がnull.

public static class NHExtensions
{
    public static IQueryOver<TRoot, TSubType> TransformUsingAliasToBean<TRoot, TSubType>(this IQueryOver<TRoot, TSubType> query, Type resultType)
    {
        ITupleSubsetResultTransformer resultTransformer = new AliasToBeanResultTransformer(resultType);
        var criteria = query.UnderlyingCriteria as NHibernate.Impl.CriteriaImpl;
        if (criteria != null)
            resultTransformer = new CacheableAliasToBeenResultTransformer(resultTransformer, criteria.Projection.Aliases);
        return query.TransformUsing(resultTransformer);
    }

    class CacheableAliasToBeenResultTransformer : ITupleSubsetResultTransformer
    {
        ITupleSubsetResultTransformer baseTransformer;
        string[] aliases;

        public CacheableAliasToBeenResultTransformer(ITupleSubsetResultTransformer baseTransformer, string[] aliases)
        {
            this.baseTransformer = baseTransformer;
            this.aliases = aliases;
        }

        public bool[] IncludeInTransform(string[] aliases, int tupleLength)
        {
            return baseTransformer.IncludeInTransform(aliases ?? this.aliases, tupleLength);
        }

        public bool IsTransformedValueATupleElement(string[] aliases, int tupleLength)
        {
            return baseTransformer.IsTransformedValueATupleElement(aliases ?? this.aliases, tupleLength);
        }

        public IList TransformList(IList collection)
        {
            return baseTransformer.TransformList(collection);
        }

        public object TransformTuple(object[] tuple, string[] aliases)
        {
            return baseTransformer.TransformTuple(tuple, aliases ?? this.aliases);
        }
    }
}

クエリは次のようになります。

SalesUnitDto result = null; 
var list = _session.QueryOver<SalesUnit>()
    .SelectList(l => l
        .Select(x => x.Id).WithAlias(() => result.Id)
        .Select(x => x.Name).WithAlias(() => result.Name))
    .TransformUsingAliasToBean(typeof(SalesUnitDto))
    .Cacheable()
    .List<SalesUnitDto>();

このシナリオでテストされ、機能しています。もちろん、すべてのQueryOverバリエーションで機能することを保証することはできません。

于 2016-12-15T19:55:51.723 に答える
1

NHibernate のこのバグは、 v4.1.0.4000で修正されました。

于 2016-12-26T11:47:46.067 に答える