C# NHibernate - 非空属性引用空值或瞬态值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/568029/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 08:32:49  来源:igfitidea点击:

NHibernate - not-null property reference a null or transient value

c#nhibernateexceptionfluent-nhibernatenhibernate-mapping

提问by brendanjerwin

I'm getting this exception (Full exception at the bottom):

我收到此异常(底部的完整异常):

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"

I've done a lot of Googling and it seems the most common cause for that error is when an association is bi-directional but only one half has been set. As in: Insurance.Patient = Patient is called but Patient.Insurances.Add(Insurance) is not. I do, in fact, have a scenario like that but I've checked the object just before calling Save with it and both Insurance.Patient and Patient.Insurances[0] are the right objects.

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

The other possibility that this exception seems to reference is a transient value. In my case everyobject is transient so I'm suspecting the root of my problem is here. However, everything needs to be transient right now because nothing has been saved yet. I would expect NHibernate to persist things rather than complain that they are not persisted.

此异常似乎引用的另一种可能性是瞬态值。就我而言,每个对象都是瞬态的,所以我怀疑问题的根源在这里。然而,现在一切都需要是暂时的,因为还没有保存任何东西。我希望 NHibernate 坚持一些事情而不是抱怨他们没有坚持。

Here are some snippets from my mappings (fluent):

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

       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();

           ...
        }

So, what could be the issue?

那么,可能是什么问题?



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:

采纳答案by Alun Harford

Another possibility is that you're saving an entire object graph, and that graph is circular, and items cannot be null. You could be giving NHibernate no legal order in which to do the inserts. (It should produce a better error message, but it produces this one).

另一种可能性是您正在保存整个对象图,并且该图是圆形的,并且项目不能为空。您可能没有给予 NHibernate 进行插入的法律命令。(它应该会产生更好的错误信息,但它会产生这个错误信息)。

Without seeing the rest of the source, it's hard to be of more help. Try removing entities from the mappings (and not saving them) until you can figure out what is causing the problem.

没有看到其余的源代码,很难有更多帮助。尝试从映射中删除实体(而不是保存它们),直到您能找出导致问题的原因。

回答by Stuart Childs

It looks like the exception originates at line 25 of your RepositoryBase.cs file, presumably when a Save() is called on one of your transient objects. Which one is being saved?

看起来异常起源于您的 RepositoryBase.cs 文件的第 25 行,大概是在您的一个瞬态对象上调用 Save() 时。哪一个正在被拯救?

Also, and it might be unrelated since I'm unfamiliar with the Fluent syntax, should the child object (the insurance in this case) have .Cascade.All on it? In standard XML schema syntax, only the parent mapping has cascade="all" on the collection of child objects.

另外,由于我不熟悉 Fluent 语法,这可能无关紧要,子对象(在这种情况下是保险)是否应该包含 .Cascade.All ?在标准 XML 模式语法中,只有父映射在子对象集合上具有级联 =“all”。

回答by Adam Fyles

I've had this problem recently and it has to do with the way NHibernate bi-directional relationships are persisted. You have the mapping correct and therefore NHibernate will perform the Patient insert no problem. Then NHibernate needs to take the key from Patients and cascade that into Insurances. Since the Patient does not yet exist, the keys do not exist and it cannot perform the second insert. The key is to set the relationship via code prior to persistence, something like this:

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

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

Now it was foreign to me that you have to set the Patient property on the collection item, but if you ignore persistence all together you will be setting this in code independent of your persistence strategy.

现在,您必须在集合项上设置 Patient 属性对我来说很陌生,但是如果您一起忽略持久性,那么您将在独立于持久性策略的代码中进行设置。

回答by Sid

not sure if it helps but this did it for me.

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

<many-to-one name="Company" column="CompanyId" cascade="all" not-null="true"/>

cascade="all" was what I missed out before

级联=“所有”是我之前错过的

回答by Akira Yamamoto

This worked for me. The important things here are that we have Referenceswith Cascade.All()and we don't have Inverse()on HasMany

这对我有用。这里最重要的事情是,我们必须ReferencesCascade.All()我们没有Inverse()HasMany

public PatientMap()
{
    HasMany(x => x.Insurances)
        .WithKeyColumn("uid_Patient")
        .Cascade.All();

    ...
}

public InsuranceMap()
{
    References(x => x.Patient, "uid_Patient")
        .Not.Nullable()
        .Cascade.All();

    ...
}