I get the error listed below when issuing either a ISession.Save or ISession.SaveOrUpdate on transient objects.
I expect NHibernate to issue 3 INSERT statements, but issues either a INSERT+UPDATE or UPDATE+UPDATE. If I change the generator class="uuid.hex" and remove the Guid.NewGuid().ToString() assignments on A/B, the test with pass.
I need to assign my own Guid before saving the objects to NHibernate. Either way, I still should be able to assign my own Guids. Not sure if the code can tell that its a guid and assumes it must already be aware of it.
Error - NHibernate.HibernateException: SQL insert, update or delete failed (expected affected row count: 1, actual affected row count: 0). Possible causes: the row was modified or deleted by another user, or a trigger is reporting misleading row count.
Hibernate version: 1.2.0.0 Alpha
Database: Sql Server 2000
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" namespace="UuidBug" assembly="UuidBug" default-lazy="false">
<class name="A" table="dbo.A">
<id name="Uuid" type="string" length="50" column="Id" access="field">
<generator class="assigned" />
</id>
<bag name="_bs" lazy="false" generic="true" inverse="false" cascade="save-update" access="field" >
<key column="AId"/>
<one-to-many class="B"/>
</bag>
</class>
<class name="B" table="dbo.B">
<id name="_uuid" type="string" length="50" column="Id" access="field">
<generator class="assigned" />
</id>
</class>
</hibernate-mapping>
Code:
using System;
using System.Collections.Generic;
namespace UuidBug
{
public class A
{
public string Uuid = Guid.NewGuid().ToString();
IList<B> _bs = new List<B>();
public IList<B> Bs { get { return _bs; } }
}
public class B
{
private string _uuid = Guid.NewGuid().ToString();
}
}
using System;
using System.Configuration;
using NHibernate;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;
using UuidBug;
using Configuration=NHibernate.Cfg.Configuration;
namespace Tests
{
[TestFixture]
public class UuidBugTests
{
private ISessionFactory _factory;
private Configuration _configuration;
[SetUp]
public void SetUp()
{
_configuration = new Configuration();
_configuration.SetProperty("hibernate.show_sql", "True");
_configuration.SetProperty("hibernate.connection.provider", "NHibernate.Connection.DriverConnectionProvider");
_configuration.SetProperty("hibernate.connection.connection_string", ConfigurationManager.AppSettings["SharedConnectionString"]);
_configuration.SetProperty("hibernate.dialect", "NHibernate.Dialect.MsSql2000Dialect");
_configuration.SetProperty("hibernate.connection.driver_class", "NHibernate.Driver.SqlClientDriver");
_configuration.AddAssembly(typeof(A).Assembly);
_factory = _configuration.BuildSessionFactory();
ExportSchema();
}
public void ExportSchema()
{
new SchemaExport(_configuration).Create(false, true);
}
public ISession OpenSession()
{
ISession session = _factory.OpenSession();
session.FlushMode = FlushMode.Commit;
return session;
}
[Test]
public void PersistTransient()
{
A a = new A();
B b1 = new B();
a.Bs.Add(b1);
B b2 = new B();
a.Bs.Add(b2);
Persist(a);
}
private void Persist(A a)
{
using (ISession session = OpenSession())
{
ITransaction transaction = session.BeginTransaction();
try
{
session.SaveOrUpdate(a);
// session.Save(a);
transaction.Commit();
}
catch (Exception e)
{
transaction.Rollback();
throw e;
}
}
}
}
}
Save log :
NHibernate: INSERT INTO dbo.A (Id) VALUES (@p0); @p0 = 'cbfc8c30-c51c-4912-93b2-c2be35fb93ee'
NHibernate: UPDATE dbo.B SET AId = @p0 WHERE Id = @p1; @p0 = 'cbfc8c30-c51c-4912-93b2-c2be35fb93ee', @p1 = '5baf9f0a-a92d-46f4-ad9b-71191209529a'
SaveOrUpdate log :
NHibernate: UPDATE dbo.B SET AId = null WHERE AId = @p0; @p0 = '4ac8e893-4ca6-4969-b019-5e2d2728d39c'
NHibernate: UPDATE dbo.B SET AId = @p0 WHERE Id = @p1; @p0 = '4ac8e893-4ca6-4969-b019-5e2d2728d39c', @p1 = '150f0663-8384-48c1-8170-7dd79c329ac8'
Log for when generator class="uuid.hex" is being used :
NHibernate: INSERT INTO dbo.A (Id) VALUES (@p0); @p0 = '7b3e193631d44bffb9421383d3807127'
NHibernate: INSERT INTO dbo.B (Id) VALUES (@p0); @p0 = '44adbcee0de446f69b753cefd3997144'
NHibernate: INSERT INTO dbo.B (Id) VALUES (@p0); @p0 = 'ce5b84b9b68540f49f63dd7cad7658cf'
NHibernate: UPDATE dbo.B SET AId = @p0 WHERE Id = @p1; @p0 = '7b3e193631d44bffb9421383d3807127', @p1 = '44adbcee0de446f69b753cefd3997144'
NHibernate: UPDATE dbo.B SET AId = @p0 WHERE Id = @p1; @p0 = '7b3e193631d44bffb9421383d3807127', @p1 = 'ce5b84b9b68540f49f63dd7cad7658cf'