我在嘗試在我正在工作的MVC 2項目中使用關聯的家族名稱列表保存客戶時拋出TransientObjectException上。在ASP.NET MVC中保存對象時引發NHibernate.TransientObjectException 2
這是類代碼:
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; }
}
我使用功能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) %>
點擊保存更改按鈕調用其傳遞迴客戶,其呼籲的Isession更新方法的存儲庫中的控制器上的方法。這就是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)
這不是重複。這個問題是關於另一個例外。 – Babakoto 2012-07-09 17:20:31
你是對的,對不起。 – 2012-07-09 17:21:45
這可能與將實際實體用作ViewModels有關。您的控制器將收到由MVC創建的實體,但未從會話獲得。創建實際的ViewModel通常更安全,然後將實體同步到實際需要更新的實體上,而不是整個實體(因爲您的視圖可能不會回發整個實體)。 – 2012-07-09 17:30:35