Asp.net mvc 4 “;not null属性引用空值或瞬时值”;在NHibernate中删除对象时

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

我已经创建了一个MVC4,并使用NHibernate来持久化模型,并用fluent NHibernate将其映射。实体有一个“Name”属性,映射方式如下:

 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");
}