私はISession.Refresh()
で(少なくとも私にとっては)奇妙な行動を経験してきました。なぜ、NHibernateは "GenericADOException:この場合、ISession.Refresh中にコレクションを初期化できませんでした"という例外をスローしますか?
私は遅延ロードされた子コレクションと、このコレクションに当てはまる読み取り専用プロパティーを持つエンティティを持っています。これらはすべて第2レベルのキャッシュに含まれています。私は、DBへのトランザクションをコミットした後、最新のデータを取得し、次のエラーを取得するのに長いセッションでISession.Refresh()
を使用 :
NHibernate.Exceptions.GenericADOException : could not initialize a collection: [Test.NUnit.DBTest.TestModel.ParentTestEntity.Children#d4251363-cf88-4684-b65a-9f330107afcf][SQL: SELECT children0_.ParentTestEntity_id as ParentTe4_1_, children0_.Id as Id1_, children0_.Id as Id42_0_, children0_.RowVersion as RowVersion42_0_, children0_.Parent_id as Parent3_42_0_ FROM "ChildTestEntity" children0_ WHERE children0_.ParentTestEntity_id=?]
----> System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type)
at NHibernate.Loader.Collection.CollectionLoader.Initialize(Object id, ISessionImplementor session)
at NHibernate.Persister.Collection.AbstractCollectionPersister.Initialize(Object key, ISessionImplementor session)
at NHibernate.Event.Default.DefaultInitializeCollectionEventListener.OnInitializeCollection(InitializeCollectionEvent event)
at NHibernate.Impl.SessionImpl.InitializeCollection(IPersistentCollection collection, Boolean writing)
at NHibernate.Collection.AbstractPersistentCollection.Initialize(Boolean writing)
at NHibernate.Collection.AbstractPersistentCollection.ReadSize()
at NHibernate.Collection.PersistentBag.get_Count()
DBTest\TestModel\EntiteTestCacheCollectionsParent.cs(25,0): at Test.NUnit.DBTest.TestModel.ParentTestEntity.get_Count()
at (Object , GetterCallback)
at NHibernate.Bytecode.Lightweight.AccessOptimizer.GetPropertyValues(Object target)
at NHibernate.Tuple.Entity.PocoEntityTuplizer.GetPropertyValuesWithOptimizer(Object entity)
at NHibernate.Tuple.Entity.PocoEntityTuplizer.GetPropertyValues(Object entity)
at NHibernate.Persister.Entity.AbstractEntityPersister.GetPropertyValues(Object obj, EntityMode entityMode)
at NHibernate.Event.Default.AbstractVisitor.Process(Object obj, IEntityPersister persister)
at NHibernate.Event.Default.DefaultRefreshEventListener.OnRefresh(RefreshEvent event, IDictionary refreshedAlready)
at NHibernate.Event.Default.DefaultRefreshEventListener.OnRefresh(RefreshEvent event)
at NHibernate.Impl.SessionImpl.FireRefresh(RefreshEvent refreshEvent)
at NHibernate.Impl.SessionImpl.Refresh(Object obj)
DBTest\NHibernateBehaviorTests.cs(610,0): at Test.NUnit.DBTest.NHibernateBehaviorTests.Test()
--NullReferenceException
at NHibernate.Engine.Loading.CollectionLoadContext.AddCollectionToCache(LoadingCollectionEntry lce, ICollectionPersister persister)
at NHibernate.Engine.Loading.CollectionLoadContext.EndLoadingCollection(LoadingCollectionEntry lce, ICollectionPersister persister)
at NHibernate.Engine.Loading.CollectionLoadContext.EndLoadingCollections(ICollectionPersister persister, IList`1 matchedCollectionEntries)
at NHibernate.Engine.Loading.CollectionLoadContext.EndLoadingCollections(ICollectionPersister persister)
at NHibernate.Loader.Loader.EndCollectionLoad(Object resultSetId, ISessionImplementor session, ICollectionPersister collectionPersister)
at NHibernate.Loader.Loader.InitializeEntitiesAndCollections(IList hydratedObjects, Object resultSetId, ISessionImplementor session, Boolean readOnly)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.LoadCollection(ISessionImplementor session, Object id, IType type)
が簡略化モデルに問題があることを示し、ユニットテストですここで
[Test]
public void Test()
{
ISession session1 = NHibernateHelper.SessionFactory.OpenSession();
ISession session2 = NHibernateHelper.SessionFactory.OpenSession();
// Create a new entity tree and persist it
ParentTestEntity parentSession1 = new ParentTestEntity();
parentSession1.AddChild(new ChildTestEntity());
session1.Save(parentSession1);
session1.Flush();
// Load the saved object into another session
ParentTestEntity parentSession2 = session2.Get<ParentTestEntity>(parentSession1.Id);
session2.Refresh(parentSession2); // Throws here
}
が関与するエンティティです:
public class ParentTestEntity
{
public virtual Guid Id { get; private set; }
public virtual long RowVersion { get; private set; }
public virtual IList<ChildTestEntity> Children { get; protected set; }
public ParentTestEntity()
{
this.Children = new List<ChildTestEntity>();
}
public virtual int Count
{
get
{
return Children.Count;
}
set { }
}
public virtual void AddChild(ChildTestEntity child)
{
if (this.Children == null)
{
this.Children = new List<ChildTestEntity>();
}
this.Children.Add(child);
child.Parent = this;
}
}
public class ChildTestEntity
{
public virtual Guid Id { get; private set; }
public virtual long RowVersion { get; private set; }
public virtual ParentTestEntity Parent { get; set; }
}
そしてそのマッピング:
前にコレクションを列挙Cache.ReadWrite()
マッピング、
を取り除く
Count
プロパティのマッピングを削除
- 、
- :私はどちらかのことがわかった私のテスト中に
public class ParentTestEntityMap : ClassMap<ParentTestEntity> { public ParentTestEntityMap() { Cache.ReadWrite(); Id(x => x.Id) .GeneratedBy.GuidComb(); Version(x => x.RowVersion); HasMany(x => x.Children) .Inverse() .Cascade.All() .Cache.ReadWrite(); Map(x => x.Count); } } public class ChildTestEntityMap : ClassMap<ChildTestEntity> { public ChildTestEntityMap() { Cache.ReadWrite(); Id(x => x.Id) .GeneratedBy.GuidComb(); Version(x => x.RowVersion); References(x => x.Parent) .Not.Nullable(); } }
Refresh
が正常に動作するには十分です。誰も私がリフレッシュ作業をするために何ができるか考えていますか?
注:
- 私は
- 、NHibernateは2.1.2と3.1.0の両方でこの現象を再現することができ、私は
Count
で空のセッターは醜いですけど、それだけのマッピングを反映するためにここです実際のモデルのエンティティ。
真実、それはモデルの悪い設計監督です(私はルールについて知っていましたが、当時それを考えなかった、私に思い出させてくれてありがとう)。しかしこれは問題にリンクされていません。テストは変更と全く同じ方法で失敗します。スタックトレースに示されているように、Countのゲッターにリンクしているようです。 –