2011-02-08 29 views
2

我簡化域模型看起來是這樣的:管理在MVC2查找和持久對象與NHibernate

public abstract class Entity<IdK> 
{ 
    public virtual IdK Code { get; protected set; } 
} 

public class Contact : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual Company Company { get; set; } 
} 

public class Company : Entity 
{ 
    public virtual string Name { get; set; } 
} 

,我已經定義了一個視圖模型:

public ContactViewModel() 
    { 
      public Guid Code { get; set; } 
      public int Version { get; set; } 

      public string Name { get; set; } 
      public string Company { get; set; } 

      public List<SelectListItem> Companies { get; set; } 
    } 

管理視圖中的我的聯繫人。
因爲我希望用戶能夠從公司的列表中選擇我添加SelectedListItem名單將在我的看法如下形式呈現:

<%=Html.ListBoxFor(m => m.Company, (List<System.Web.Mvc.SelectListItem>)Model.Companies)%> 

現在,當用戶提交我的表單在保存之前,我用我的模型重新映射了我的視圖模型。
我填充我的聯繫人並使用ContactViewModel.Company的id創建類型爲Company的對象以與Contact類的屬性關聯。
由於我不想從數據庫中提取整個公司,所以我只填寫了id。 但是,當我堅持我的聯繫方式時,我收到一個異常:「非空屬性引用空或暫時的Domain.Contact.Company」
用MVC + Nhibernate來管理查找和持久性的最佳解決方案是什麼?
你有什麼建議從你的經驗?

回答

2

不幸的是,對於NHibernate和查找,您不能只將ID屬性分配給公司對象的新實例,然後將該公司對象分配給聯繫人。

通常我會做的是在我的倉庫,假設你不能改變的公司信息時,保存的聯繫人是這樣的:

public Contact Save(Contact contact) 
{ 
    if(contact.Company.Id > 0) 
     contact.Company = Session.Load<Company>(contact.Company.Id); 

    Session.SaveOrUpdate(contact); 
} 

總的來說,我發現這使您可以封裝邏輯的加載公司,並且還可以讓您在單一會話中保持良好狀態。

以這種方式使用Session.Load避免擊中描述here

如果你不這樣做數據庫,有什麼你基本上說NHibernate的是,你有,你有一個公司對象分配了一個ID,現在想要將它保存爲所有屬性都設置爲Null或空字符串值或任何,這不是你想要的。

或者你可以創建一個保存特定的域對象,看起來像這樣:

public abstract class Entity<IdK> 
{ 
    public virtual IdK Code { get; protected set; } 
} 

public class SavableContact : Entity 
{ 
    public virtual string Name { get; set; } 
    public virtual IdK CompanyId { get; set; } 
} 

直接映射到聯繫人表中您的數據庫,這樣當你保存這個實體,你可以從字面上只是映射回CompanyId從你的視圖模型和NHibernate將只保存該值,並不關心公司對象。

這是一個確定最適合你的情況。我個人更喜歡第一種選擇,因爲額外的邏輯有助於簡化領域模型,但是如果您正在創建並公開API,那麼第二種方法可能更有意義。

+0

謝謝lomaxx。我想我會選擇第一個選項。這是你管理查找的方式嗎? – LeftyX 2011-02-08 11:47:04