NHibernate Guid.Comb执行Insert后跟Update

时间:2014-03-19 10:07:13

标签: c# nhibernate fluent-nhibernate

我有以下实体:

public class Entity
{
    public virtual Guid Id { get; protected set; }
    public virtual String Name { get; set; }
}

使用以下映射:

public class EntityMap : ClassMap<Entity>
{
    public EntityMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Name).Not.Nullable();
    }
}

执行以下代码时出错:

using(var tx = Session.BeginTransaction())
{        
    var entity = GetSomethingFromTheDatabase();
    if(entity == null)
    {
        Session.Save(new Entity());
    }
    entity.Name = "test";
    tx.Commit();
}

错误是:

NHibernate.PropertyValueException : not-null property references a null or transient value Entity.Name

当我使属性Name可以为空时,一切正常,但NHibernate发出一个Insert语句(带有Name=null)后跟一个Update语句(带Name='test'

所以:为什么NHibernate在用值更新之前尝试插入我的实体?这就是自动增量id生成器的工作方式。我们试图通过Guid.Comb来避免这种情况。如果我阅读文档,Guid.Comb应该生成ID而无需进入数据库。

编辑:

  • 我澄清了一些代码以显示我们想要做的事情。我们希望在数据库中不存在时插入实体。
  • 数据库语句仅在提交事务时执行。因此,当调用Save()时,没有任何反应。但是当调用tx.Commit()时,会发出插入并紧接着更新。我认为NHibernate会保存所有更改的值并将它们放在一个Insert中。

2 个答案:

答案 0 :(得分:1)

是否在执行.Save时立即发出插入?

也许您应该在发出保存之前设置entity.Name

我一直强烈认为,如果要创建实体,构造函数应该采用所有必需的字段来构造对象。数据库中不可为空的字段是必填字段。

答案 1 :(得分:0)

因为在修改它之前保存它?当您调用.Save时,实体将得到验证,并且如果需要持久化,或者在其被刷新或事务完成之前等待。当你调用Save时,它有一个空值的属性,所以你得到了异常。

Console.WriteLine(session.Save(..))

返回实体的生成ID。您可以看到该值是否与数据库中的值相对应。

但我确实假设在刷新或提交之前不会对数据库进行任何往返。