次の例のような状況があります。
Employee
2 つの子コレクションを持つ1 つの親エンティティ:Addresses
およびPhones
single roundtrip
アドレスと電話番号が初期化された状態ですべての従業員を取得する必要がありcache the query
、Cacheable()
.
使用:
var baseQuery = session
.Query<Employee>()
.Cacheable();
baseQuery
.FetchMany(e => e.Addresses)
.ToFuture();
var list = baseQuery
.FetchMany(e => e.Phones)
.ToFuture()
.ToList();
動作するはずですが、次の例外が発生します。
NHibernate.PropertyAccessException
メッセージ:
Exception occurred getter of NHibernateTest.Objects.Entity`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].Id
スタックトレース:
at NHibernate.Properties.BasicPropertyAccessor.BasicGetter.Get(Object target) in p:\nhibernate-core\src\NHibernate\Properties\BasicPropertyAccessor.cs:line 213
at NHibernate.Tuple.Entity.AbstractEntityTuplizer.GetIdentifier(Object entity) in p:\nhibernate-core\src\NHibernate\Tuple\Entity\AbstractEntityTuplizer.cs:line 139
at NHibernate.Persister.Entity.AbstractEntityPersister.GetIdentifier(Object obj, EntityMode entityMode) in p:\nhibernate-core\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 3890
at NHibernate.Persister.Entity.AbstractEntityPersister.IsTransient(Object entity, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Persister\Entity\AbstractEntityPersister.cs:line 3676
at NHibernate.Engine.ForeignKeys.IsTransient(String entityName, Object entity, Nullable`1 assumed, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Engine\ForeignKeys.cs:line 194
at NHibernate.Engine.ForeignKeys.GetEntityIdentifierIfNotUnsaved(String entityName, Object entity, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Engine\ForeignKeys.cs:line 250
at NHibernate.Type.ManyToOneType.Disassemble(Object value, ISessionImplementor session, Object owner) in p:\nhibernate-core\src\NHibernate\Type\ManyToOneType.cs:line 137
at NHibernate.Impl.MultipleQueriesCacheAssembler.Disassemble(Object value, ISessionImplementor session, Object owner) in p:\nhibernate-core\src\NHibernate\Impl\MultipleQueriesCacheAssembler.cs:line 33
at NHibernate.Cache.StandardQueryCache.Put(QueryKey key, ICacheAssembler[] returnTypes, IList result, Boolean isNaturalKeyLookup, ISessionImplementor session) in p:\nhibernate-core\src\NHibernate\Cache\StandardQueryCache.cs:line 74
at NHibernate.Impl.MultiQueryImpl.ListUsingQueryCache() in p:\nhibernate-core\src\NHibernate\Impl\MultiQueryImpl.cs:line 749
at NHibernate.Impl.MultiQueryImpl.List() in p:\nhibernate-core\src\NHibernate\Impl\MultiQueryImpl.cs:line 415
at NHibernate.Impl.FutureQueryBatch.GetResultsFrom(IMultiQuery multiApproach) in p:\nhibernate-core\src\NHibernate\Impl\FutureQueryBatch.cs:line 24
at NHibernate.Impl.FutureBatch`2.GetResults() in p:\nhibernate-core\src\NHibernate\Impl\FutureBatch.cs:line 73
at NHibernate.Impl.FutureBatch`2.get_Results() in p:\nhibernate-core\src\NHibernate\Impl\FutureBatch.cs:line 31
at NHibernate.Impl.FutureBatch`2.GetCurrentResult[TResult](Int32 currentIndex) in p:\nhibernate-core\src\NHibernate\Impl\FutureBatch.cs:line 79
at NHibernate.Impl.FutureBatch`2.<>c__DisplayClass4`1.<GetEnumerator>b__3() in p:\nhibernate-core\src\NHibernate\Impl\FutureBatch.cs:line 63
at NHibernate.Impl.DelayedEnumerator`1.<get_Enumerable>d__0.MoveNext() in p:\nhibernate-core\src\NHibernate\Impl\DelayedEnumerator.cs:line 26
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Tests.Tests.CacheableFetchManyAndToFutureTest() in D:\somepath\Tests.cs:line 262
内部例外:
System.Reflection.TargetException
メッセージ:
Object does not match target type.
スタックトレース:
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target)
at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index)
at NHibernate.Properties.BasicPropertyAccessor.BasicGetter.Get(Object target) in p:\nhibernate-core\src\NHibernate\Properties\BasicPropertyAccessor.cs:line 207
次のようにクエリを実行すると、結果としてデカルト積が生成され、効果がないため、機能しません。2 つの住所と 2 つの電話を持つ 1 人の従業員がいると、データベース内の一意の住所と電話はそれぞれ Addresses コレクションと Phones コレクションに 2 回表示されます。サーバーで受信した後に結果を区別することは、適切なオプションではありません。
var list = session
.Query<Employee>()
.FetchMany(e => e.Addresses)
.FetchMany(e => e.Phones)
.Cacheable()
.ToList();
FetchMany()
and ToFuture()
(no )のみを使用してクエリをCacheable()
実行すると、対応する住所と電話 (重複なし) を持つすべての従業員が 1 回のラウンドトリップで正しく返されますが、クエリがキャッシュされないため、将来の同一の要求に対する最適化は行われません。
var baseQuery = session
.Query<Employee>();
baseQuery
.FetchMany(e => e.Addresses)
.ToFuture();
var list = baseQuery
.FetchMany(e => e.Phones)
.ToFuture()
.ToList();
TLDR: 1 回のラウンドトリップで初期化された住所と電話番号を持つすべての従業員を取得し、クエリをレベル 2 キャッシュにキャッシュする方法は? 返信ありがとうございます。