我有以下实体:
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中。答案 0 :(得分:1)
是否在执行.Save时立即发出插入?
也许您应该在发出保存之前设置entity.Name
。
我一直强烈认为,如果要创建实体,构造函数应该采用所有必需的字段来构造对象。数据库中不可为空的字段是必填字段。
答案 1 :(得分:0)
因为在修改它之前保存它?当您调用.Save
时,实体将得到验证,并且如果需要持久化,或者在其被刷新或事务完成之前等待。当你调用Save时,它有一个空值的属性,所以你得到了异常。
Console.WriteLine(session.Save(..))
返回实体的生成ID。您可以看到该值是否与数据库中的值相对应。
但我确实假设在刷新或提交之前不会对数据库进行任何往返。