2012-09-13 109 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列...它始终保持为空。

相关问题