NHibernate – not-null属性引用null或transient值

我收到此exception(底部的完全例外):

NHibernate.PropertyValueException was unhandled by user code Message="not-null property references a null or transient valueClearwave.Models.Encounters.Insurance.Patient" Source="NHibernate" EntityName="Clearwave.Models.Encounters.Insurance" PropertyName="Patient" 

我已经做了很多谷歌搜索,似乎这个错误最常见的原因是当一个关联是双向的,但只设置了一半。 如:保险。患者=患者被叫,但是Patient.Insurances.Add(保险)不是。 事实上,我确实有这样的场景但我在调用Save之前检查了对象,并且Insurance.Patient和Patient.Insurances [0]都是正确的对象。

此exception似乎引用的另一种可能性是瞬态值。 在我的情况下, 每个对象都是暂时的,所以我怀疑问题的根源在这里。 但是,现在一切都需要暂时,因为还没有保存。 我希望NHibernate能够持久存在而不是抱怨它们不会被持久存在。

以下是我映射的一些片段(流利):

  public PatientMap() { WithTable("tPatient"); Id(x => x.Id, "uid_Patient").GeneratedBy.GuidComb ().Access.AsReadOnlyPropertyThroughCamelCaseField(); HasMany(x => x.Insurances).WithKeyColumn("uid_Patient") .Cascade.All() .Inverse(); ... } public InsuranceMap() { WithTable("tPatientInsuranceInfo"); Id(x => x.Id, "uid_PatientInsuranceInfo").GeneratedBy.GuidComb ().Access.AsReadOnlyPropertyThroughCamelCaseField(); References(x => x.Patient, "uid_Patient").Not.Nullable ().Cascade.All(); ... } 

那么,问题可能是什么?


 NHibernate.PropertyValueException was unhandled by user code Message="not-null property references a null or transient valueClearwave.Models.Encounters.Insurance.Patient" Source="NHibernate" EntityName="Clearwave.Models.Encounters.Insurance" PropertyName="Patient" StackTrace: at NHibernate.Engine.Nullability.CheckNullability(Object[] values, IEntityPersister persister, Boolean isUpdate) 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.DefaultMergeEventListener.EntityIsTransient (MergeEvent event, IDictionary copyCache) at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge (MergeEvent event, IDictionary copyCache) at NHibernate.Impl.SessionImpl.FireSaveOrUpdateCopy(IDictionary copiedAlready, MergeEvent event) at NHibernate.Impl.SessionImpl.SaveOrUpdateCopy(String entityName, Object obj, IDictionary copiedAlready) at NHibernate.Engine.CascadingAction.SaveUpdateCopyCascadingAction.Cascade (IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeToOne(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeAssociation(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeProperty(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything) at NHibernate.Event.Default.AbstractSaveEventListener.CascadeBeforeSave (IEventSource source, IEntityPersister persister, Object entity, Object anything) at NHibernate.Event.Default.DefaultMergeEventListener.EntityIsTransient (MergeEvent event, IDictionary copyCache) at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge (MergeEvent event, IDictionary copyCache) at NHibernate.Impl.SessionImpl.FireSaveOrUpdateCopy(IDictionary copiedAlready, MergeEvent event) at NHibernate.Impl.SessionImpl.SaveOrUpdateCopy(String entityName, Object obj, IDictionary copiedAlready) at NHibernate.Engine.CascadingAction.SaveUpdateCopyCascadingAction.Cascade (IEventSource session, Object child, String entityName, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeToOne(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeAssociation(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeProperty(Object child, IType type, CascadeStyle style, Object anything, Boolean isCascadeDeleteEnabled) at NHibernate.Engine.Cascade.CascadeOn(IEntityPersister persister, Object parent, Object anything) at NHibernate.Event.Default.AbstractSaveEventListener.CascadeBeforeSave (IEventSource source, IEntityPersister persister, Object entity, Object anything) at NHibernate.Event.Default.DefaultMergeEventListener.EntityIsTransient (MergeEvent event, IDictionary copyCache) at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge (MergeEvent event, IDictionary copyCache) at NHibernate.Event.Default.DefaultMergeEventListener.OnMerge (MergeEvent event) at NHibernate.Impl.SessionImpl.FireSaveOrUpdateCopy(MergeEvent event) at NHibernate.Impl.SessionImpl.SaveOrUpdateCopy(Object obj) at Clearwave.Models.Data.Util.RepositoryBase`2.Save(EntityType& entity) in C:\Projects\ClearWave\Src\Common\Domain Models \Clearwave.Models.Data-NHibernate\Util\RepositoryBase.cs:line 25 at IntegrationWebServices.FromMirth.SubmitMessage(Message theMessage, Guid providerOrganizationId) at SyncInvokeSubmitMessage(Object , Object[] , Object[] ) at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke (Object instance, Object[] inputs, Object[]& outputs) at System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin (MessageRpc& rpc) InnerException: 

另一种可能性是您正在保存整个对象图,并且该图是循环的,并且项不能为空。 您可能会给NHibernate没有合法的订单来执行插入操作。 (它应该产生更好的错误信息,但它产生了这个)。

如果没有看到其他来源,很难获得更多帮助。 尝试从映射中删除实体(而不是保存它们),直到找出导致问题的原因。

不确定它是否有帮助,但这对我来说。

  

cascade =“all”是我之前错过的

我最近遇到了这个问题,它与NHibernate双向关系的持久化方式有关。 您的映射是正确的,因此NHibernate将执行患者插入没有问题。 然后NHibernate需要从患者那里获取密钥并将其级联到保险中。 由于患者尚不存在,因此密钥不存在且无法执行第二次插入。 关键是在持久化之前通过代码设置关系,如下所示:

 patient = new Patient(); patient.Insurances.Add( new Insurance{ Patient = patient } ); repository.Save( patient); 

现在,我不得不在集合项上设置Patient属性,但是如果你忽略持久性,你将在代码中设置它,而不依赖于持久性策略。

这对我有用。 这里重要的是我们有Cascade.All() References ,我们在HasMany上没有Inverse()

 public PatientMap() { HasMany(x => x.Insurances) .WithKeyColumn("uid_Patient") .Cascade.All(); ... } public InsuranceMap() { References(x => x.Patient, "uid_Patient") .Not.Nullable() .Cascade.All(); ... } 

看起来exception来自RepositoryBase.cs文件的第25行,可能是在您的一个瞬态对象上调用Save()时。 哪一个被保存?

另外,它可能是不相关的,因为我不熟悉Fluent语法,如果子对象(在这种情况下是保险)上有.Cascade.All吗? 在标准XML模式语法中,只有父映射在子对象集合上具有cascade =“all”。