Je réalise une transaction NHibernate assez complexe dans un système financier, créant un paiement, enregistrant les écritures dans le grand livre, vérifiant si le paiement correspond au montant total d'une facture, en indiquant si la facture est payée dans son intégralité, etc. beaucoup de choses amusantes. Naturellement, cela doit se faire dans une transaction unique.
Lorsque j'essaie de valider la modification de la session, le message d'erreur suivant s'affiche:
Error dehydrating property value for C3.DataModel.CFAPTransaction.Vendor
Googler cela n'a pas fait beaucoup de disque. Quelqu'un peut-il me dire ce que cela signifie et où je dois concentrer mes efforts de débogage?
UPDATE
Par demande, voici le message d'erreur complet:
NHibernate.PropertyValueException: Error dehydrating property v alue for C3.DataModel.CFAPTransaction.Vendor --->
NHibernate.HibernateException: Impossible de résoudre le problème de la propriété: APVendorI à NHibernate.Tuple.Entity.EntityMetamodel.GetPropertyIndex (String property) à l’aide de l’utilisateur (en anglais). GetPropertyValue (Object obj, String propertyName, EntityMode entityMode) à NHibernate.Type.EntityType.GetIdentifier (Valeur de l'objet, IDBCommand, session) sur NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (id d’objet, champs Object [], objet rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, table Int32, instruction IDbCommand, session IDession, base de données ISessionImplementor, index Int32 - - Fin de la trace de pile d'exception interne --- sur NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (Object ID, Champs Object [], Object rowId, Boolea n [] includeProperty, Boolean [] [] includeColumns, table Int32, instruction IDbCommand, session ISessionImplementor, index Int32) à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (id d'objet, champs Object [], booléen [] non, Int32 j , SqlCommandInfo sql, Object obj, ISessionImplementor session) à NHibernate.Persister.Entity.AbstractEntityPersister.In (Identifiant d’objet, Champs [], Object obj, ISessionImplementor session) à NHibernate.Action.Ection.EntityInsertAction.Active (). ActionQueue.Execute (IExecutable exécutable) à NHibernate.Engine.ActionQueue.ExecuteActions (liste IList) à NHibernate.Engine.ActionQueue.ExecuteActions () à NHibernate.Event.Default.AbstractFlushingEventListener.Parfait de vue (1). DefaultFlushEventListener.OnFlush (événement FlushEvent) à NHibernate.Impl.SessionImpl.Flush () à NHibernate.Transaction.AdoTransaction.Commit () à C3.DataModel.Repositories.NHUnitOfWork.Save () dans C:\projects taModel.Generated\Generated\NHibernateRepositories.generated.cs: ligne 2659 à C3.WebUI.Areas.Finance.Controllers.AccountsPayableController.CreatePayment (modèle CreatePaymentModel) dans C:\projects\C3\C3.WebUI\Areas\Finance\Controllers AccountsPayableController.cs: ligne 434
UPDATE En lançant NHibernate en mode DEBUG, je reçois un tas de choses comme celle-ci:
traitement en cas de demande de traitement APVendor.Transactions done processing cascade NHibernate.Engine.CascadingAction + SaveUpdateCascadingAction pour: C3.DataModel.APVendor NHibernate.Event.Default.ListenerEventListener ERREUR Impossible de synchroniser l’état de la base de données avec la session Vendor ---> NHibernate.HibernateException: Impossible de résoudre la propriété: APVendorId à NHibernate.Tuple.Entity.Entity.EntityMetamodel.GetPropertyIndex (String propertyName) à NHibernate.Tuple.Entity.AbstractEntityTuplizer.Grossiterdocumentationalribal formateur .Entity.AbstractEntityPersister.GetProp ertyValue (Object obj, String propertyName, EntityMode entityMode) à NHibernate.Type.EntityType.GetIdentifier (Valeur de l'objet, ISessionImplementor session) à la valeur NHibernate.Type.EntityType.GetIdentifier session) sur NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (id d’objet, champs Object [], objet rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, table Int32, instruction IDbCommand, session IDession, base de données ISessionImplementor, index Int32 - - Fin de la trace de pile d'exception interne --- sur NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (Object id, champs Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, table Int32, instruction IDbCommand, Session ISessionImplementor, index Int32) à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (id d'objet, champs Object [], booléen [] non NULL, int32 j, SqlCommandInfo sql, objet obj, session ISessionImplementor) à NHiberna te.Persister.Entity.AbstractEntityPersister.Insert (id d'objet, champs Object [], obj d'objet, session ISessionImplementor) à NHibernate.Action.EntityInsertAction.Execute () à NHibernate.Engine.ActionQueue.Execute (IExecutable). .ActionQueue.ExecuteActions (liste IList) à NHibernate.Engine.ActionQueue.ExuteActions () à NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions (session), C3.WebUI.Finance. Finance.Controllers.AccountsPayableController: Aucune information supplémentaire. NHibernate.PropertyValueException: erreur lors de la déshydratation de la propriété C3.DataModel.CFAPTransaction.Vendor ---> NHibernate.HibernateException: impossible de résoudre la propriété: APVendorId dans NHibernate.Tuple.Entity.EntityMEmityMetamodel.Gal. La description de la propriété .ManyToOneType.NullSafeSet (IDbCommand st, Object, index Int32, Boolean [] settable, session ISessionImplementor) à NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (ID d'objet, Object [] champs, Object row] [] [] includeColumns, table Int32, instruction IDbCommand, session ISessionImplementor, index Int32) --- Fin de la trace de pile d'exception interne --- à NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate (ID d'objet, champs Object [], Objet rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, table Int32, instruction IDbCommand, session ISessionImplementor, index Int32) à NHibernate.Pister .Entity.AbstractEntityPersister.Insert (ID d'objet, champs Object [], Boolean [] notNull, Int32 j, SqlCommandInfo sql, Object obj, ISessionImplementor session) à NHibernate.Persister.Entity.AbstractEntityPersister.Insert (ID d'objet) , Object obj, session ISessionImplementor) à NHibernate.Action.EntityInsertAction.Execute () à NHibernate.Engine.ActionQueue.Execute (exécutable IExecutable) à NHibernate.Engine.ActionQueue.ExecuteActive () à (NHist). ) sur NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions (session IEventSource) sur NHibernate.Event.Default.DefaultFlushEventListener.OnFlush (événement FlushEvent) sur NHibernate.Impl.SessionImpl.Flush () sur NHiber nate.Transaction.AdoTransaction.Commit () à C3.DataModel.Repositories.NHUnitOfWork.Save () dans C:\projects\C3\C3.DataModel.Generated\NHibernateRepositories.generated.cs: ligne 2659 à C3.WebUI. Areas.Finance.Controllers.AccountsPayableController.CreatePayment (modèle CreatePaymentModel) dans C:\projects\C3\C3.WebUI\Areas\Finance\Contrôleurs\AccountsPayableController.cs: ligne 434
Il ne semble pas que cela se produise lors de l'interrogation de la base de données. J'ai l'impression qu'il est difficile de créer un groupe d'objets, de les relier, puis d'essayer de les conserver, mais c'est une pure supposition.
Il est probable que nhibernate n'indique pas la propriété d'erreur correcte. Vérifiez les propriétés adjacentes dans le fichier de mappage, recherchez les erreurs de relation entre les types de données de votre base de données et les types de données de .net ou les colonnes répétées dans les propriétés ... cochez également cette option. link NHibernate Fluent - IndexOutOfRange
Vous devriez vérifier le mappage CFAPTransaction. Il semble que vous vouliez spécifier un fournisseur pour chaque transaction. Dans ce cas, votre mappage doit être comme ci-dessous le code.
public CFAPTransactionMap()
{
HasOne(x => x.Vendor).ForeignKey("VendorId").Cascade.All();
...
}
Dans mon cas, c’était une spécification d’identité manquante sur le serveur SQL.
Objet simple:
public class Employee
{
public virtual int ID { get; set; }
}
Cartographie:
public class EmployeeMap : ClassMapping<Employee>
{
public EmployeeMap()
{
Id(x => x.ID, map => { map.Generator(Generators.Identity); map.UnsavedValue(0); });
}
}
SQL:
Voici la colonne ID avec la contrainte de clé primaire.
Et ici, vous pouvez voir la spécification d’identité manquante, qui est à l’origine du problème.
Pour résoudre le problème, vous devez spécifier la colonne ID comme IDENTITY
I.e.
CREATE TABLE EMPLOYEE
(
ID int NOT NULL IDENTITY(0, 1)
);
J'ai rencontré la même erreur. Voici mes exemples de mappages:
ManyToOne(x => x.objPerson, map => { map.Column("PersonID"); map.NotNullable(false); });
Property(x => x.intPersonID, map => map.Column("PersonID"));
Si j'essayais de conserver/sauvegarder ceci dans ma base de données en ne renseignant que la propriété intPersonID
et en rendant objPerson
null, cela provoquerait une erreur de déshydratation sur toutes vos propriétés!
La raison pour laquelle je ne fais que remplir intPersonID
est d'empêcher l'interrogation de la base de données pour obtenir le objPerson
avant de l'enregistrer dans la base de données. Malheureusement, cela provoquera une erreur, j'ai donc modifié mes correspondances et corrigé ceci:
ManyToOne(x => x.objPerson, map => { map.Column("PersonID"); map.NotNullable(false); });
Ou si je veux éviter d'interroger la base de données en récupérant l'objet entier, je vais simplement utiliser ce mappage à la place:
Property(x => x.intPersonID, map => map.Column("PersonID"));
Mais les combiner n'est pas possible.