当我尝试在我正在处理的 MVC 2 项目中使用关联的姓氏列表保存客户时,我遇到了 NHibernate 抛出 TransientObjectException 的问题。
这是类的代码:
public class Customer
{
public virtual Guid Id { get; set; }
public virtual int Version { get; set; }
public virtual string Forename { get; set; }
public virtual IList<FamilyName> FamilyNames { get; set; }
}
public class FamilyName
{
public virtual Guid Id { get; set; }
public virtual int Version { get; set; }
public virtual string Name{ get; set; }
public virtual bool IsCurrent { get; set; }
public virtual Patient Patient { get; set; }
}
我正在使用 Fluent NHibernate 进行持久性,映射如下所示:
public CustomerMap()
{
Table("Customers");
Id(x=>x.Id).GeneratedBy.GuidComb();
Version(x => x.Version);
Map(x => x.Forename).Not.Nullable();
HasMany(x => x.FamilyNames)
.Inverse()
.Cascade.All();
}
public FamilyNameMap()
{
Table("FamilyNames");
Id(x=>x.Id).GeneratedBy.GuidComb();
Version(x => x.Version);
Map(x => x.Name).Not.Nullable();
Map(x => x.IsCurrent).Not.Nullable();
References(x => x.Patient).Not.Nullable();
}
我有一个强类型的 EditCustomerDetails 视图,其中包含以下代码:
<% using (Html.BeginForm("SaveChanges", "CustomerDetails")) { %>
<input type="submit" value="Save changes"/>
<%= Html.HiddenFor(customer => customer.Id) %>
<%= Html.HiddenFor(customer => customer.Version) %>
<label>Forename:</label>
<%= Html.TextBoxFor(customer => customer.Forename)%>
<label>Family Names</label>
<div class="familyNames">
<%= Html.EditorFor(customer => customer.FamilyNames)%>
</div>
<% } %>
这是 FamilyName 类的自定义编辑器模板:
<%= Html.HiddenFor(name => name.Id) %>
<%= Html.HiddenFor(name => name.Version) %>
<%= Html.HiddenFor(name => name.Patient.Id) %>
<label>Name:</label>
<%= Html.TextBoxFor(name => name.Name) %>
<label>Is Current?:</label>
<%= Html.CheckBoxFor(name =>name.IsCurrent) %>
单击 Save Changes 按钮调用控制器上的一个方法,该方法将客户传递回存储库,该存储库调用 ISession 上的 Update 方法。这是 NHibernate.TransientObjectException 与消息“对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例”的消息一起抛出的地方。
我不知道为什么会这样。我已经进入了代码,并且所有数据都从视图中正确传回,所有对象都具有正确的属性值。我能够找到解决此问题的唯一建议是参考在映射中设置 Cascade.All ,这就是我一直在做的事情。
有任何想法吗?
编辑:这是错误消息:
ERROR Shipping.Web.Filters.UnhandledErrorAttribute - An unhandled exception has occurred
Shipping.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing. Type: Shipping.Domain.Entities.Customer, Entity: Haemoglobinopathy.Domain.Entities.Customer
at NHibernate.Engine.ForeignKeys.GetEntityIdentifierIfNotUnsaved(String entityName, Object entity, ISessionImplementor session)
at NHibernate.Type.EntityType.GetIdentifier(Object value, ISessionImplementor session)
at NHibernate.Type.ManyToOneType.NullSafeSet(IDbCommand st, Object value, Int32 index, Boolean[] settable, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Dehydrate(Object id, Object[] fields, Object rowId, Boolean[] includeProperty, Boolean[][] includeColumns, Int32 table, IDbCommand statement, ISessionImplementor session, Int32 index)
at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)
at NHibernate.Action.EntityUpdateAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
at Haemoglobinopathy.Persistence.TransactionAttribute.OnActionExecuted(ActionExecutedContext filterContext) in C:\dev\Projects\Haemoglobinopathy\Haemoglobinopathy.Persistence\TransactionAttribute.cs:line 26
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<>c__DisplayClassf.<InvokeActionMethodWithFilters>b__c()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodFilter(IActionFilter filter, ActionExecutingContext preContext, Func`1 continuation)
at System.Web.Mvc.ControllerActionInvoker.<>c__DisplayClassd.<>c__DisplayClassf.<InvokeActionMethodWithFilters>b__c()
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethodWithFilters(ControllerContext controllerContext, IList`1 filters, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)