Fluent Nhibernate - 映射列表会导致 NullReferenceException?
我有以下类和流畅的映射:
public class A {
public virtual int Id { get; private set; }
public virtual string MyString { get; set; }
public virtual IList<B> MyChildren { get; set; }
}
public class B {
public virtual int Id { get; private set; }
public virtual DateTime TheDate { get; set; }
}
public sealed class AMap : ClassMap<A> {
public AMap() {
Id(x => x.Id).GeneratedBy.Native().UnsavedValue(0);
Map(x => x.MyString);
HasMany(x => x.MyChildren).AsList(x => x.Column("Ordinal")).KeyColumn("AId").Not.KeyNullable();
}
}
public sealed class BMap : ClassMap<B> {
public BMap() {
Id(x => x.Id).GeneratedBy.Native().UnsavedValue(0);
Map(x => x.TheDate);
}
}
这会导致 A 的以下映射:
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="A" table="`A`">
<id name="Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
<column name="Id" />
<generator class="native" />
</id>
<property name="MyString" type="AnsiString">
<column name="MyString" length="150" not-null="true" />
</property>
<list name="MyChildren" mutable="true">
<key not-null="true">
<column name="AId" />
</key>
<index>
<column name="Ordinal" />
</index>
<one-to-many class="B" />
</list>
</class>
但是当我实际尝试保存 A 的实例时,我得到一个 NullReferenceException:
System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Collection.PersistentList.GetSnapshot(ICollectionPersister persister)
at NHibernate.Engine.CollectionEntry..ctor(ICollectionPersister persister, IPersistentCollection collection)
at NHibernate.Engine.StatefulPersistenceContext.AddNewCollection(ICollectionPersister persister, IPersistentCollection collection)
at NHibernate.Event.Default.WrapVisitor.ProcessArrayOrNewCollection(Object collection, CollectionType collectionType)
at NHibernate.Event.Default.WrapVisitor.ProcessCollection(Object collection, CollectionType collectionType)
at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Object value, IType type)
at NHibernate.Event.Default.WrapVisitor.ProcessValue(Int32 i, Object[] values, IType[] types)
at NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types)
at NHibernate.Event.Default.AbstractSaveEventListener.VisitCollectionsBeforeSave(Object entity, Object id, Object[] values, IType[] types, IEventSource source)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
我在这里做错了什么?
澄清:这就是我使用这些类的方式:
var a = new A { MyChildren = new List<B> { new B { TheDate = DateTime.Now } } };
a.MyChildren[0].Parent = a;
session.Save(a);
I have the following classes and fluent mappings:
public class A {
public virtual int Id { get; private set; }
public virtual string MyString { get; set; }
public virtual IList<B> MyChildren { get; set; }
}
public class B {
public virtual int Id { get; private set; }
public virtual DateTime TheDate { get; set; }
}
public sealed class AMap : ClassMap<A> {
public AMap() {
Id(x => x.Id).GeneratedBy.Native().UnsavedValue(0);
Map(x => x.MyString);
HasMany(x => x.MyChildren).AsList(x => x.Column("Ordinal")).KeyColumn("AId").Not.KeyNullable();
}
}
public sealed class BMap : ClassMap<B> {
public BMap() {
Id(x => x.Id).GeneratedBy.Native().UnsavedValue(0);
Map(x => x.TheDate);
}
}
This results in the following mapping for A:
<class xmlns="urn:nhibernate-mapping-2.2" mutable="true" name="A" table="`A`">
<id name="Id" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" unsaved-value="0">
<column name="Id" />
<generator class="native" />
</id>
<property name="MyString" type="AnsiString">
<column name="MyString" length="150" not-null="true" />
</property>
<list name="MyChildren" mutable="true">
<key not-null="true">
<column name="AId" />
</key>
<index>
<column name="Ordinal" />
</index>
<one-to-many class="B" />
</list>
</class>
But when I actually try to save an instance of A, I get a NullReferenceException
:
System.NullReferenceException : Object reference not set to an instance of an object.
at NHibernate.Collection.PersistentList.GetSnapshot(ICollectionPersister persister)
at NHibernate.Engine.CollectionEntry..ctor(ICollectionPersister persister, IPersistentCollection collection)
at NHibernate.Engine.StatefulPersistenceContext.AddNewCollection(ICollectionPersister persister, IPersistentCollection collection)
at NHibernate.Event.Default.WrapVisitor.ProcessArrayOrNewCollection(Object collection, CollectionType collectionType)
at NHibernate.Event.Default.WrapVisitor.ProcessCollection(Object collection, CollectionType collectionType)
at NHibernate.Event.Default.AbstractVisitor.ProcessValue(Object value, IType type)
at NHibernate.Event.Default.WrapVisitor.ProcessValue(Int32 i, Object[] values, IType[] types)
at NHibernate.Event.Default.AbstractVisitor.ProcessEntityPropertyValues(Object[] values, IType[] types)
at NHibernate.Event.Default.AbstractSaveEventListener.VisitCollectionsBeforeSave(Object entity, Object id, Object[] values, IType[] types, IEventSource source)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
What am I doing wrong here?
Clarification: This is how I'm using the classes:
var a = new A { MyChildren = new List<B> { new B { TheDate = DateTime.Now } } };
a.MyChildren[0].Parent = a;
session.Save(a);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您应该将
MyChildren = New List();
添加到 A 的构造函数中You should add
MyChildren = New List<B>();
to your constructor for A子集合的关键列不应该是“Id”(而不是“AId”)吗?我认为这就是你问题的根源......
Shouldn't your key column be "Id" (as opposed to "AId") for the child collection? I think that this is the source of your problem...
我想通了。上面的示例实际上确实有效,但我试图重现的问题仍在运行,导致了相同的错误。抱歉...
问题是我们创建了这个 ChildList 类,我们为 MyChildren 属性返回了该类。它只是包装了 List(或者 NHibernate 用于持久列表的任何具体列表),但它负责在集合中添加或删除的任何实例上设置 Parent 属性。
显然,这会导致 NHibernate 在保存新实例时出现问题。返回一个正常的具体列表是可行的。
I figured this out. The sample above actually does work, but the issue I was trying to reproduce was still running, causing the same error. Sorry about that...
The issue is that we had created this ChildList class, which we returned for the MyChildren property. It simply wrapped the List (or whatever concrete list NHibernate uses for persistent lists), but it took care of setting the Parent property on whatever instance was added or removed from the collection.
Apparently this causes NHibernate problems when saving even a new instance. Returning a normal concrete List works.