我一直在寻找并且用NHibernate找不到这个问题的好答案。
我正在使用一个使用NHibernate的API。我正在进行数据传输,我正在尝试使用他们的User对象来保存用户数据。
我创建了对象
User objUser = new User();
他们有一个映射文件,指定id设置为identity
<id name="Id" column="UserId" type="int">
<generator class="native" />
</id>
但我的一个要求是将旧ID保存到用户表。我需要能够暂时将标识插入设置为ON并保存记录,但仍然可以使用User对象来保存关联的数据。
我尝试过这样的事情
using (ISession session = MyDatabaseFactory.SessionFactory.OpenSession())
{
using (ITransaction trans = session.BeginTransaction())
{
session.CreateSQLQuery("SET IDENTITY_INSERT Users ON").UniqueResult();
session.Save(objUser, objUser.Id);
session.Flush();
trans.Commit();
session.CreateSQLQuery("SET IDENTITY_INSERT Users OFF").UniqueResult();
session.Close();
objUser= session1.Merge(objUser);
}
}
但是在尝试稍后再次保存用户对象时
objUser.Passwords.Add("password1");
objUser.Save()
我收到错误:具有相同标识符值的其他对象已与会话
关联答案 0 :(得分:0)
Save()
尝试将新对象插入数据库。
您应该尝试Update()
,它会更新数据库中现有记录的持久对象。
您还可以使用SaveOrUpdate()
决定使用上述哪一项。
再次调用Save()
,我认为它正在尝试插入具有相同Id的另一条记录。
The answer here有更多详情。
答案 1 :(得分:0)
如果您的要求仅适用于非常特殊的情况,例如:数据库更新或迁移,您可以使用不同的会话工厂,其中ID是assigend:
<id name="Id" column="UserId" type="int">
<generator class="assigned" />
</id>
并指定id:
User objUser = new User() { UserId = 42 };
如果您的案例与正常的商业案例紧密结合,这不是一个很好的解决方案。
您可以尝试实施自己的IIdentifierGenerator
。不要指望它简单直接。您可能有机会派生IdentityGenerator
,合并Assigned
生成器中的一些代码并将此SET IDENTITY_INSERT Users ON
内容放入其中...生成器需要知道何时使用哪种策略。例如。当id仍为0时,让SQL Server创建一个,当它是其他东西时,插入指定的值。