NHibernate: ошибка дегидратирующего свойства. Что это за черт?
Я делаю довольно сложную транзакцию NHibernate в финансовой системе, создавая платеж, записывая записи в книгу, проверяя, является ли платеж общей суммой счета-фактуры, если это так, что счет-фактура полностью оплачен, и т.д.... много веселья. Естественно, это должно произойти внутри одной транзакции.
Когда я пытаюсь зафиксировать изменение сеанса, я получаю следующую ошибку:
Error dehydrating property value for C3.DataModel.CFAPTransaction.Vendor
В Googling этого не оказалось много записей. Может ли кто-нибудь сказать мне, что это значит, и где мне нужно сосредоточить свои усилия по отладке?
UPDATE
По запросу, вот полное сообщение об ошибке:
NHibernate.PropertyValueException: Error dehydrating property v alue for C3.DataModel.CFAPTransaction.Vendor --->
NHibernate.HibernateException: Невозможно разрешить свойство: APVendorId в NHibernate.Tuple.Entity.EntityMetamodel.GetPropertyIndex(строка propertyName) в NHibernate.Tuple.Entity.AbstractEntityTuplizer.GetPropertyValue(Объект объект, String propertyPath) в NHibernate.Persister.Entity.AbstractEntityPersister.GetPropertyValue(Объект obj, String propertyName, EntityMode entityMode) при NHibernate.Type.EntityType.GetIdentifier(значение объекта, ISessionImplementor) в NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, значение объекта, Индекс Int32, Boolean [] устанавливаемый, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Объект id, Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, таблица Int32, команда IDbCommand, ISessionImplementor, индекс Int32) --- Конец внутреннего исключения трассировка стека --- при NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Объект id, Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, таблица Int32, команда IDbCommand, Сеанс ISessionImplementor, индекс Int32) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Идентификатор объекта, Object [], Boolean [] notNull, Int32 j, SqlCommandInfo sql, Object obj, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Идентификатор объекта, Object [], Object obj, сеанс ISessionImplementor) в NHibernate.Action.EntityInsertAction.Execute() at NHibernate.Engine.ActionQueue.Execute(исполняемый файл IExecutable) в NHibernate.Engine.ActionQueue.ExecuteActions(список IList) в NHibernate.Engine.ActionQueue.ExecuteActions() в NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource сессии) в NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent событие) в NHibernate.Impl.SessionImpl.Flush() в NHibernate.Transaction.AdoTransaction.Commit() at C3.DataModel.Repositories.NHUnitOfWork.Save() в C:\Проекты\C3\C3.DataModel.Generated\Сформированные\NHibernateRepositories.generated.cs: линия 2659 в C3.WebUI.Areas.Finance.Controllers.AccountsPayableController.CreatePayment(CreatePaymentModel модель) в C:\проекты\С3\C3.WebUI\Области\Финансы\Контроллеры\AccountsPayableController.cs: линия 434
UPDATE
Бросив NHibernate в режим DEBUG, я получаю кучу таких вещей:
каскад обработки NHibernate.Engine.CascadingAction + SaveUpdateCascadingAction для: C3.DataModel.APVendor каскадный NHibernate.Engine.CascadingAction + SaveUpdateCascadingAction для коллекция: C3.DataModel.APVendor.Transactions сделанный каскадом NHibernate.Engine.CascadingAction + SaveUpdateCascadingAction для коллекция: C3.DataModel.APVendor.Transactions сделано обработка каскада NHibernate.Engine.CascadingAction + SaveUpdateCascadingAction для: C3.DataModel.APVendor NHibernate.Event.Default.AbstractFlushingEventListener ОШИБКА Не удалось синхронизировать состояние базы данных с сеансом NHibernate.PropertyValueException: ошибка дегидратирования значения свойства для C3.DataModel.CFAPTransaction.Vendor --- > NHibernate.HibernateException: Невозможно разрешить свойство: APVendorId в NHibernate.Tuple.Entity.EntityMetamodel.GetPropertyIndex(строка propertyName) в NHibernate.Tuple.Entity.AbstractEntityTuplizer.GetPropertyValue(Объект объект, String propertyPath) в NHibernate.Persister.Entity.AbstractEntityPersister.GetPropertyValue(Объект obj, String propertyName, EntityMode entityMode) при NHibernate.Type.EntityType.GetIdentifier(значение объекта, ISessionImplementor) в NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, значение объекта, Индекс Int32, Boolean [] устанавливаемый, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Объект id, Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, таблица Int32, команда IDbCommand, ISessionImplementor, индекс Int32) --- Конец внутреннего исключения трассировка стека --- при NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Объект id, Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, таблица Int32, команда IDbCommand, Сеанс ISessionImplementor, индекс Int32) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Идентификатор объекта, Object [], Boolean [] notNull, Int32 j, SqlCommandInfo sql, Object obj, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Идентификатор объекта, Object [], Object obj, сеанс ISessionImplementor) в NHibernate.Action.EntityInsertAction.Execute() at NHibernate.Engine.ActionQueue.Execute(исполняемый файл IExecutable) в NHibernate.Engine.ActionQueue.ExecuteActions(список IList) в NHibernate.Engine.ActionQueue.ExecuteActions() в NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource сессия) C3.WebUI.Areas.Finance.Controllers.AccountsPayableController ERROR C3.WebUI.Areas.Finance.Controllers.AccountsPayableController: Нет дополнительной информации. NHibernate.PropertyValueException: ошибка дегидратирования значения свойства для C3.DataModel.CFAPTransaction.Vendor --- > NHibernate.HibernateException: Невозможно разрешить свойство: APVendorId в NHibernate.Tuple.Entity.EntityMetamodel.GetPropertyIndex(строка propertyName) в NHibernate.Tuple.Entity.AbstractEntityTuplizer.GetPropertyValue(Объект объект, String propertyPath) в NHibernate.Persister.Entity.AbstractEntityPersister.GetPropertyValue(Объект obj, String propertyName, EntityMode entityMode) при NHibernate.Type.EntityType.GetIdentifier(значение объекта, ISessionImplementor) в NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, значение объекта, Индекс Int32, Boolean [] устанавливаемый, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Объект id, Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, таблица Int32, команда IDbCommand, ISessionImplementor, индекс Int32) --- Конец внутреннего исключения трассировка стека --- при NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Объект id, Object [], Object rowId, Boolean [] includeProperty, Boolean [] [] includeColumns, таблица Int32, команда IDbCommand, Сеанс ISessionImplementor, индекс Int32) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Идентификатор объекта, Object [], Boolean [] notNull, Int32 j, SqlCommandInfo sql, Object obj, сеанс ISessionImplementor) в NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Идентификатор объекта, Object [], Object obj, сеанс ISessionImplementor) в NHibernate.Action.EntityInsertAction.Execute() at NHibernate.Engine.ActionQueue.Execute(исполняемый файл IExecutable) в NHibernate.Engine.ActionQueue.ExecuteActions(список IList) в NHibernate.Engine.ActionQueue.ExecuteActions() в NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource сессии) в NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent событие) в NHibernate.Impl.SessionImpl.Flush() в NHibernate.Transaction.AdoTransaction.Commit() at C3.DataModel.Repositories.NHUnitOfWork.Save() в C:\Проекты\C3\C3.DataModel.Generated\Сформированные\NHibernateRepositories.generated.cs: линия 2659 в C3.WebUI.Areas.Finance.Controllers.AccountsPayableController.CreatePayment(CreatePaymentModel модель) в C:\проекты\С3\C3.WebUI\Области\Финансы\Контроллеры\AccountsPayableController.cs: линия 434
Не похоже, что это происходит при запросе базы данных. У меня есть чувство, что у меня есть проблемы со мной, создавая кучу объектов, связывая их, а затем пытаясь их удержать, но это чистое предположение.
Ответы
Ответ 1
Вероятно, что nhibernate не показывает правильное свойство ошибки, проверяет смежные свойства в файле сопоставления, ищет ошибки в отношении между типами данных из вашей базы данных и типами данных из .net или повторяющихся столбцов в свойствах... также проверьте эту ссылку Fluent NHibernate - IndexOutOfRange
Ответ 2
Вы должны проверить сопоставление CFAPTransaction. Похоже, вы хотели указать одного поставщика для каждой транзакции. В этом случае ваше сопоставление должно быть как ниже кода.
public CFAPTransactionMap()
{
HasOne(x => x.Vendor).ForeignKey("VendorId").Cascade.All();
...
}
Ответ 3
В моем случае это была недостающая спецификация идентификатора на SQL-сервере.
Простой объект:
public class Employee
{
public virtual int ID { get; set; }
}
Mapping:
public class EmployeeMap : ClassMapping<Employee>
{
public EmployeeMap()
{
Id(x => x.ID, map => { map.Generator(Generators.Identity); map.UnsavedValue(0); });
}
}
SQL:
Вот столбец идентификатора с ограничением первичного ключа.
![столбец идентификаторов с ограничением]()
И здесь вы можете увидеть недостающую спецификацию идентификатора, которая вызывает проблему.
![Отсутствует спецификация идентификатора]()
Чтобы решить проблему, вы должны указать столбец ID как IDENTITY
то есть.
CREATE TABLE EMPLOYEE
(
ID int NOT NULL IDENTITY(0, 1)
);
Ответ 4
Я столкнулся с той же ошибкой. Это мои сопоставления с образцами:
ManyToOne(x => x.objPerson, map => { map.Column("PersonID"); map.NotNullable(false); });
Property(x => x.intPersonID, map => map.Column("PersonID"));
Если я попытался сохранить/сохранить это в своей базе данных, заполнив только свойство intPersonID
и сделав нулевое значение objPerson
, это приведет к ошибке дегидратации во всех ваших свойствах!
Причина, по которой я просто заполняю intPersonID
, заключается в том, чтобы предотвратить запрос в базе данных, чтобы получить objPerson
перед сохранением в базе данных. К сожалению, это вызовет ошибку, поэтому я изменил свои сопоставления и исправил это:
ManyToOne(x => x.objPerson, map => { map.Column("PersonID"); map.NotNullable(false); });
Или, если я хочу предотвратить запрос в базе данных, получив весь объект, я просто использую это сопоставление:
Property(x => x.intPersonID, map => map.Column("PersonID"));
Но объединение их невозможно.