2012-09-13 40 views
2

我有一個相當直接的映射:由於空版本列而無法保存實體。 NHibernate的

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="XXXX.DomainLayer" namespace="XXXX.DomainLayer.Entities"> 
    <class name="Project" optimistic-lock="version"> 
     <id name="Id" column="ProjectID" unsaved-value="00000000-0000-0000-0000-000000000000"> 
      <generator class="guid.comb" /> 
     </id> 
     <version name="Version" generated="always" type="BinaryBlob" /> 
    <!-- poperties --> 
    </class> 
</hibernate-mapping> 

和相應的實體如下:

public abstract class AbstractEntity<T> where T : AbstractEntity<T> { 
    public virtual Guid Id { get; protected set; } 
    public virtual Byte[] Version { get; set; } 

    // other properties, methods 
} 
public class Project : AbstractEntity<Project>, IAggregateRoot { 
    // specific properties, methods 
} 

我出口的模式來SqlServer。那裏一切都很好。但每次我發佈表單時(create actionSqlServer拋出一個美國例外:

無法插入NULL值插入「版本」列...

所以insert得到恢復。

最初的問題就解決了

實際的問題是,我不能讓編輯過的實體 - 我越來越StaleObjectStateException

行被另一事務更新或刪除(或者未保存值的映射是不正確的)[XXXX.DomainLayer.Entities.Project#707991d0-07b5-45fc-99ed-a0cc00db108a]

檢查當在SQLServer很顯然,無論如何版本列都保持爲空。

控制器代碼

public ActionResult Create() { 
    return View("Edit", new EditProjectViewModel()); 
} 

[HttpGet] 
public ActionResult Edit(Guid id) { 
    var project = this.repo.Get(id); 
    var model = Mapper.Map<Project, EditProjectViewModel>(project); 

    return View(model); 
} 

[HttpPost, ValidateAntiForgeryToken] 
public ActionResult Edit(EditProjectViewModel model) { 
    if(ModelState.IsValid) { 

     model.InitiatedBy = this.userService.GetUser(some_param); 
     model.ProblemContext = BBCode.ToHtml(model.ProblemContext); 

     var project = Mapper.Map<EditProjectViewModel, Project>(model); 

     if(project.IsTransient) { 
      this.repo.Add(project); 
     } 
     else { 
      try { 
       this.repo.Update(project); 
      } 
      catch(NHibernate.StaleObjectStateException e) { 
       // Some logic here 
      } 
     } 

     return RedirectToAction("Index", "Home", new { area = "" }); 
    } // if(ModelState.IsValid) { 
    return View(model); 
} 

凡庫Update方法是這樣的:

public void Update(T entity) { 
    using(var tx = this.session.BeginTransaction()) { 
     /* try { */ 
      this.session.SaveOrUpdate(entity); 
      tx.Commit(); 
     /* } 
     catch(StaleObjectStateException) { 
      try { 
       entity = this.session.Merge(entity); 
       tx.Commit(); 
      } 
      catch(Exception) { 
       tx.Rollback(); 
       throw; 
      } 
     } 
     */ 
    } 
} 

DI件

public class DataAccessModule : NinjectModule { 
    public override void Load() { 
     this.Bind<ISessionFactory>() 
      .ToMethod(c => new Configuration().Configure().BuildSessionFactory()) 
      .InSingletonScope(); 

     this.Bind<ISession>() 
      .ToMethod(ctx => ctx.Kernel.TryGet<ISessionFactory>().OpenSession()) 
      .InRequestScope(); 

     this.Bind(typeof(IRepository<>)).To(typeof(Repository<>)) 
      .InRequestScope(); 
    } 
} 

謝謝!

+0

您是否嘗試將「sql-type」設置爲「timestamp」和「unsaved-value」爲「null」(請參閱​​我的答案)? – Alexander

回答

4

嘗試將sql-type =「timestamp」添加到版本列映射中。例如。

<version name="Version" generated="always" unsaved-value="null" type="BinaryBlob"> 
    <column name="Version" not-null="false" sql-type="timestamp"/> 
</version> 
+0

老兄,那工作!謝謝! – lexeme

0

您確定您使用的是正確的<version>嗎?

NHibernate documentation

版本號可以是類型的Int64,的Int32,Int16類型,蜱,時間戳, 或時間跨度的(或它們可爲空的對口.NET 2.0)。

+0

在本傑明珀金斯的書中找到它http://www.amazon.com/Working-NHibernate-Wrox-Blox-ebook/dp/B005UQLK6W/ref=sr_1_2?ie=UTF8&qid=1347539632&sr=8-2&keywords=working+with + nhibernate + 3.0(第174頁) – lexeme

+0

我看到了......不知道那是什麼問題。也許你可以嘗試其他類型? –

+0

無論如何,這是你做的一個好點! – lexeme

0

我無意中發現了一個解決方案,它是很明顯的:

<id name="Id" column="ProjectID" unsaved-value="00000000-0000-0000-0000-000000000000"> 
     <generator class="guid.comb" /> 
    </id> 
    <version name="Version" generated="always" type="BinaryBlob"> 
     <column name="Version" not-null="false" /> 
    </version> 
<!-- ... the rest --> 

編輯

但這種改變向我介紹了另一個問題:SqlServer不更新Version列...它始終保持爲空。

相關問題