我有一个非常直接的映射:
<?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
很明显 Version 列无论如何都保持为空。
控制器代码
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();
}
}
谢谢!