我有一个相当直接的映射:由于空版本列而无法保存实体。 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 action
)SqlServer
抛出一个美国例外:
无法插入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();
}
}
谢谢!
您是否尝试将“sql-type”设置为“timestamp”和“unsaved-value”为“null”(请参阅我的答案)? – Alexander