0

我是Castle Windsor/Fluent NHibernate/NHibernate的新手,我正努力將它們全部用於.NET MVC3項目中作爲學習練習。Fluent NHibernate/Castle Windsor,Id = 0當試圖更新

經歷this優秀教程得走了,並試圖stay away from repositories,結束了與下面的類/映射:

// Entities 
public abstract class EntityBase 
{ 
    public virtual int Id { get; private set; } 
    public virtual DateTime Modified { get; set; } 
} 

public class Section : EntityBase 
{ 
    public virtual String Name { get; set; } 
    public virtual int Sortorder { get; set; } 
    public virtual IList<ContentPage> Pages { get; set; } 

    public Section() 
    { 
     Pages = new List<ContentPage>(); 
    } 

    public virtual void AddContentPage(ContentPage contentPage) 
    { 
     contentPage.Section = this; 
     this.Pages.Add(contentPage); 
    } 
} 

public class ContentPage : EntityBase 
{ 
    public virtual String Title { get; set; } 
    public virtual int Sortorder { get; set; } 
    public virtual String MetaKeywords { get; set; } 
    public virtual String MetaDescription { get; set; } 
    public virtual String Slug { get; set; } 

    public virtual Section Section { get; set; } 
} 

//Mappings 
public abstract class EntityBaseMap<T> : ClassMap<T> where T : EntityBase 
{ 
    public EntityBaseMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Modified); 
    } 
} 

public class SectionMap : EntityBaseMap<Section> 
{ 
    public SectionMap() 
    { 
     Map(x => x.Name); 
     Map(x => x.Sortorder); 
     HasMany(x => x.Pages) 
      .Inverse() 
      .Cascade.All(); 
    } 
} 
public class ContentPageMap : EntityBaseMap<ContentPage> 
{ 
    public ContentPageMap() 
    { 
     Map(x => x.Title); 
     Map(x => x.Sortorder); 
     Map(x => x.MetaKeywords); 
     Map(x => x.MetaDescription); 
     Map(x => x.Slug); 
     References(x => x.Section); 

    } 
} 

// SectionsController 

    private readonly ISession session; 

    public ActionResult Edit(int id) 
    { 
     Section section = session.QueryOver<Section>().Where(x => x.Id == id).SingleOrDefault(); 
     if (section == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(section); 
    } 

    [HttpPost] 
    public ActionResult Edit(Section section) 
    { 
     section.Modified = DateTime.Now; 
     if (ModelState.IsValid) 
     { 
      session.Update(section); 
      return RedirectToAction("Index"); 
     } 
     return View(); 
    } 

我遇到的是當我編輯「部分」的問題,表單顯示正常,隱藏的'id'具有正確的值。但是,當提交表單時,「編輯」操作中id列的值爲0.有趣的是,「修改」也是EntityBase類的一部分,但填充得很好。

不用說,添加一個新的'部分'不是一個問題,因爲數據庫正確地生成了id。

所以我知道我絕對錯過了某個地方,而我只是沒有看到它。任何人都可以擺脫任何我失蹤的光?

編輯:多虧@下面Linkgoron的回答,添加一個ViewModel ...

public class SectionViewModel 
{ 
    public int Id { get; set; } 

    [Required(ErrorMessage = "Section Name is required")] 
    [StringLength(25, ErrorMessage = "Name must be less than 25 characters")] 
    public String Name { get; set; } 
    [Required] 
    public int Sortorder { get; set; } 
} 

// Updated Controller methods 
public ActionResult Edit(int id) 
    { 
     Section section = session.Load<Section>(id); 
     if (section == null) 
     { 
      return HttpNotFound(); 
     } 
     return View(section); 
    } 

    [HttpPost] 
    public ActionResult Edit(SectionViewModel sectionInputModel) 
    { 
     var section = session.Get<Section>(sectionInputModel.Id); 
     section.Modified = DateTime.Now; 
     if (ModelState.IsValid) 
     { 
      Mapper.CreateMap<SectionViewModel, Section>(); 
      Mapper.Map(sectionInputModel, section); 
      session.SaveOrUpdate(section); 
      return RedirectToAction("Index"); 
     } 
     return View(); 
    } 

現在我得到正確的ID,並把它映射了正確的爲好,但SaveOrUpdate不似乎修改數據庫中的數據。我還錯過了什麼?

編輯2:Doh!

所需沖洗即

session.SaveOrUpdate(section); 
session.Flush(); 
return RedirectToAction("Index"); 

感謝。

+0

你不應該每次都使用Mapper.CreateMap (),你只需要執行一次CreateMap,在application_start中執行。這是一個沉重的操作,使用反射。另外,當使用nhibernate時,你應該總是在一個事務內部執行一些東西http://nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions – Linkgoron 2011-04-23 07:28:05

+0

沒問題。以上只是爲了讓它工作。非常感謝指針! – seekay 2011-04-23 17:01:56

回答

1

我相信這是因爲Id被設置爲私有,所以Model Binder不能設置該值。

處理此問題的最佳方法是創建一個ViewModel。 ViewModel的基礎知識是爲每個視圖創建一個較小的模型,並在域模型和視圖模型之間進行映射。

基本上,當你不使用ViewModels時,你會打開重張/張貼(Brad Wilson's blog)這是一個嚴重的安全問題。還有其他好處,比如更好的重構,更好的驗證和更好的分離關注。

更多信息:

ViewModel Best Practices

Using view models in ASP.NET MVC 3

你還要一些無關的東西去那裏,這樣的修改的屬性。 NHibernate的內置了支持使用版本映射(Ayende's blogfluent nhibernate

而且這種屬性,它使用的會話通過ID而不是查詢對象加載對象的Get /加載方法的優選(Ayende's blog )。

+0

感謝[a] ViewModels [b] Get/Load方法的信息,[c] Version屬性 - 超級有用!仍然有一個問題,保存和版本作爲時間戳,但會研究後者更多 – seekay 2011-04-23 03:29:00

相關問題