web-dev-qa-db-ja.com

NHibernate-nullではないプロパティがnullまたは一時的な値を参照する

私はこの例外を取得しています(下部の完全な例外):

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"

私は多くのグーグル操作を行いましたが、そのエラーの最も一般的な原因は、関連付けが双方向であるが、半分しか設定されていない場合です。のように:Insurance.Patient = Patientが呼び出されますが、Patient.Insurances.Add(Insurance)は呼び出されません。実際、そのようなシナリオがありますが、Saveを呼び出す直前にオブジェクトをチェックしました。Insurance.PatientとPatient.Insurances [0]の両方が適切なオブジェクトです。

この例外が参照していると思われるもう1つの可能性は、一時的な値です。私の場合everyオブジェクトは一時的なので、問題の根本はここにあると思います。ただし、まだ何も保存されていないため、現時点ではすべてが一時的である必要があります。私は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:
24
brendanjerwin

別の可能性としては、オブジェクトグラフ全体を保存していて、そのグラフは円形であり、アイテムをnullにすることはできません。挿入を行うための法的な命令をNHibernateに与えていない可能性があります。 (より適切なエラーメッセージが生成されるはずですが、これは生成されます)。

残りのソースを確認しなければ、これ以上の助けになることは困難です。何が問題の原因であるかがわかるまで、マッピングからエンティティを削除してください(保存しないでください)。

18
Alun Harford

それが役立つかどうかはわかりませんが、これでうまくいきました。

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

cascade = "all"は、私が以前に見逃したものでした

10
Sid

私は最近この問題を抱えており、NHibernateの双方向の関係が持続する方法に関係しています。マッピングが正しいため、NHibernateは患者挿入を問題なく実行します。次に、NHibernateは患者からキーを取得し、それを保険にカスケードする必要があります。患者がまだ存在しないため、キーは存在せず、2番目の挿入を実行できません。重要なのは、永続化する前に、次のようなコードで関係を設定することです。

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

現在、コレクションアイテムにPatientプロパティを設定する必要があるのは私には関係がありませんが、永続性をすべて一緒に無視する場合は、永続性戦略とは関係なくコードでこれを設定します。

8
Adam Fyles

これでうまくいきました。ここで重要なのは、ReferencesCascade.All()があり、HasManyInverse()がないことです。

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

    ...
}

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

    ...
}
1
Akira Yamamoto

例外は、RepositoryBase.csファイルの25行目から発生しているようです。おそらく、一時オブジェクトの1つでSave()が呼び出されたと考えられます。どちらが保存されていますか?

また、私がFluent構文に慣れていないため、子オブジェクト(この場合は保険)に.Cascade.Allが必要ですか?標準のXMLスキーマ構文では、親マッピングのみが子オブジェクトのコレクションにcascade = "all"を持っています。

0
Stuart Childs