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

相关问题