Asp.net mvc 4 “;not null属性引用空值或瞬时值”;在NHibernate中删除对象时
我已经创建了一个MVC4,并使用NHibernate来持久化模型,并用fluent NHibernate将其映射。实体有一个“Name”属性,映射方式如下:Asp.net mvc 4 “;not null属性引用空值或瞬时值”;在NHibernate中删除对象时,asp.net-mvc-4,nhibernate,Asp.net Mvc 4,Nhibernate,我已经创建了一个MVC4,并使用NHibernate来持久化模型,并用fluent NHibernate将其映射。实体有一个“Name”属性,映射方式如下: Map(x => x.Name).Not.Nullable().Length(100); 我已经创建了一个用于查看对象列表的表,并允许我编辑、查看对象详细信息和删除它们。 当我删除该对象时,视图层会将模型Id发回相应的控制器,并且控制器会通过存储库对象尝试删除该对象 [HttpPost] public ActionRe
Map(x => x.Name).Not.Nullable().Length(100);
我已经创建了一个用于查看对象列表的表,并允许我编辑、查看对象详细信息和删除它们。
当我删除该对象时,视图层会将模型Id发回相应的控制器,并且控制器会通过存储库对象尝试删除该对象
[HttpPost]
public ActionResult DeleteElement(Element element)
{
Element deletedElement = repository.Delete(element);
TempData["message"] = string.Format("{0} has been deleted.",deletedElement.Name);
return RedirectToAction("Index");
}
表视图的部分内容:
<td>
@using (Html.BeginForm("DeleteMenu", "Admin"))
{
@Html.Hidden("ID", item.ID)
<input type="submit" value="Delete"/>
}
</td>
@使用(Html.BeginForm(“删除菜单”、“管理”))
{
@Html.Hidden(“ID”,item.ID)
}
因此,视图仅将elemntID发回控制器。和元素对象只有其ID。其所有属性均为null。当由于name属性为null而尝试删除该对象时,存储库中的会话对象无法删除该对象,因为name字段为null
错误消息:
not null属性引用null或瞬态值元素。Name
如果我只是删除一个对象并拥有主键,为什么nHibernate关心其他字段是否为空?
如何仅删除具有id的对象
public IQueryable GetAll()
{
返回session.Query();
}
公共IQueryable Get(表达式谓词)
{
返回GetAll(),其中(谓词);
}
公共作废删除(T实体)
{
删除(实体);
}
首先从NHibernate检索实例,并将其用作传递到Delete
的对象
发生的事情是,您正在创建一个NHibernate权限之外的对象(在MVC模型绑定中)。由于您在HTML表单中只指定ID,因此当模型绑定器完成时,模型的属性也都为空
当您将此对象传递给NHibernate时,它将注意到会话没有观察到它,并尝试附加它,这将看到大量脏属性值(所有为null),因此首先尝试刷新对它的更改
您的操作应如下所示:
[HttpPost]
public ActionResult DeleteElement(int id)
{ var element = repository.Get(e => e.Id == id).First();
repository.Delete(element);
TempData["message"] = string.Format("{0} has been deleted.",deletedElement.Name);
return RedirectToAction("Index");
}
我建议在您的存储库中添加一个方法,该方法由NHibernate包装Load
<代码>加载非常有用,因为它使用您指定的ID创建观察到的对象实例,但在您访问ID以外的属性之前,它不会实际命中数据库。对于您知道对象存在但只需要指针(例如删除实体或在关系中添加实体)的情况,它非常有用
更新的存储库:
public IQueryable<T> GetAll()
{
return session.Query<T>();
}
public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
{
return GetAll().Where(predicate);
}
public T DeferredGet(int id) // I like to call it DeferredGet, you can call it Load or whatever you want
{
return session.Load<T>(id);
}
public void Delete(T entity)
{
session.Delete(entity);
}
谢谢你详细的回答帮了大忙,问题很快就解决了。
public IQueryable<T> GetAll()
{
return session.Query<T>();
}
public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
{
return GetAll().Where(predicate);
}
public T DeferredGet(int id) // I like to call it DeferredGet, you can call it Load or whatever you want
{
return session.Load<T>(id);
}
public void Delete(T entity)
{
session.Delete(entity);
}
[HttpPost]
public ActionResult DeleteElement(int id)
{ var element = repository.DeferredGet(id); // will not actually hit the database, saving you a query.
repository.Delete(element); // deletes the element normally.
TempData["message"] = string.Format("{0} has been deleted.",deletedElement.Name);
return RedirectToAction("Index");
}