同一个NHibernate Linq查询中的Cacheable(),FetchMany()和ToFuture()

遇到类似于以下示例的情况:

1个父实体具有2个子集合的EmployeeAddressesPhones

我需要在single roundtrip检索所有员工的初始化地址和电话,并使用Cacheable()缓存在二级缓存中实现cache the query

使用:

 var baseQuery = session .Query() .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.b__3() in p:\nhibernate-core\src\NHibernate\Impl\FutureBatch.cs:line 63 at NHibernate.Impl.DelayedEnumerator`1.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 

内部exception:

 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 

查询如下不起作用,因为它生成笛卡尔积,结果是无效的。 让1名员工拥有2个地址和2部电话,数据库中的每个唯一地址和电话将在地址和电话集合中出现两次。 在服务器上收到结果后,结果不同是不太好的选择。

 var list = session .Query() .FetchMany(e => e.Addresses) .FetchMany(e => e.Phones) .Cacheable() .ToList(); 

仅使用FetchMany()ToFuture() (无Cacheable() )查询将在1次往返中正确返回具有相应地址和电话(无重复项)的所有员工,但由于查询未缓存,因此未来的相同请求不会进行优化:

 var baseQuery = session .Query(); baseQuery .FetchMany(e => e.Addresses) .ToFuture(); var list = baseQuery .FetchMany(e => e.Phones) .ToFuture() .ToList(); 

TLDR:如何检索在单个往返中初始化的地址和电话的所有员工,并将查询缓存在二级缓存中? 谢谢你的回复!