I am experimenting with NHibernate (version 2.1.0.4000) with Fluent NHibernate Automapping.
My test set of entities persists fine with default integer IDs
I am now trying to use Guid IDs with the entities. Unfortunately changing the Id property to a Guid seems to stop NHibernate inserting objects.
Here is the entity class:
public class User
{
public virtual int Id { get; private set; }
public virtual string FirstName { get; set; }
public virtual string LastName { get; set; }
public virtual string Email { get; set; }
public virtual string Password { get; set; }
public virtual List<UserGroup> Groups { get; set; }
}
And here is the Fluent NHibernate configuration I am using:
SessionFactory = Fluently.Configure()
//.Database(SQLiteConfiguration.Standard.InMemory)
.Database(MsSqlConfiguration.MsSql2008.ConnectionString(@"Data Source=.\SQLEXPRESS;Initial Catalog=NHibernateTest;Uid=NHibernateTest;Password=password").ShowSql())
.Mappings(m =>
m.AutoMappings.Add(
AutoMap.AssemblyOf<TestEntities.User&g开发者_如何学编程t;()
.UseOverridesFromAssemblyOf<UserGroupMappingOverride>()))
.ExposeConfiguration(x =>
{
x.SetProperty("current_session_context_class","web");
})
.ExposeConfiguration(Cfg => _configuration = Cfg)
.BuildSessionFactory();
Here is the log output when using an integer ID:
16:23:14.287 [4] DEBUG NHibernate.Event.Default.DefaultSaveOrUpdateEventListener - saving transient instance
16:23:14.291 [4] DEBUG NHibernate.Event.Default.AbstractSaveEventListener - saving [TestEntities.User#<null>]
16:23:14.299 [4] DEBUG NHibernate.Event.Default.AbstractSaveEventListener - executing insertions
16:23:14.309 [4] DEBUG NHibernate.Event.Default.AbstractSaveEventListener - executing identity-insert immediately
16:23:14.313 [4] DEBUG NHibernate.Persister.Entity.AbstractEntityPersister - Inserting entity: TestEntities.User (native id)
16:23:14.321 [4] DEBUG NHibernate.AdoNet.AbstractBatcher - Opened new IDbCommand, open IDbCommands: 1
16:23:14.321 [4] DEBUG NHibernate.AdoNet.AbstractBatcher - Building an IDbCommand object for the SqlString: INSERT INTO [User] (FirstName, LastName, Email, Password) VALUES (?, ?, ?, ?); select SCOPE_IDENTITY()
16:23:14.322 [4] DEBUG NHibernate.Persister.Entity.AbstractEntityPersister - Dehydrating entity: [TestEntities.User#<null>]
16:23:14.323 [4] DEBUG NHibernate.Type.StringType - binding null to parameter: 0
16:23:14.323 [4] DEBUG NHibernate.Type.StringType - binding null to parameter: 1
16:23:14.323 [4] DEBUG NHibernate.Type.StringType - binding 'ertr' to parameter: 2
16:23:14.324 [4] DEBUG NHibernate.Type.StringType - binding 'tretret' to parameter: 3
16:23:14.329 [4] DEBUG NHibernate.SQL - INSERT INTO [User] (FirstName, LastName, Email, Password) VALUES (@p0, @p1, @p2, @p3); select SCOPE_IDENTITY();@p0 = NULL, @p1 = NULL, @p2 = 'ertr', @p3 = 'tretret'
and here is the output when using a Guid:
16:50:14.008 [4] DEBUG NHibernate.Event.Default.DefaultSaveOrUpdateEventListener - saving transient instance
16:50:14.012 [4] DEBUG NHibernate.Event.Default.AbstractSaveEventListener - generated identifier: d74e1bd3-1c01-46c8-996c-9d370115780d, using strategy: NHibernate.Id.GuidCombGenerator
16:50:14.013 [4] DEBUG NHibernate.Event.Default.AbstractSaveEventListener - saving [TestEntities.User#d74e1bd3-1c01-46c8-996c-9d370115780d]
This is where it silently fails, with no exception thrown or further log entries.
It looks like it is generating the Guid ID correctly for the new object, but is just not getting any further than that.
Is there something I need to do differently in order to use Guid IDs?
Thanks,
Dan.
You should check your application (non-mapping) code and be sure that you are committing your NHibernate ITransaction
instance.
When using an integer ID and the native
or identity
generator, NHibernate must insert a new instance immediately so that the ID value is generated (even if the transaction hasn't been committed yet). When using an identifier strategy like guid.comb
that does not depend on the database to generate IDs, NHibernate will not actually execute the insert until the enclosing transaction is committed.
I'm not completely sure about the auto-mapping situation.
However, one thing I can tell you is to be sure to set the Guid on new instances of your class to Guid.Empty when you construct them, rather than to Guid.NewGuid(). This signals to NHibernate that the object is new and should be inserted rather than updated; much the same as zero for an int property. NHibernate will back-update the property to a generated Guid on insertion.
public class Cat { public Cat() : base() { this.Id = Guid.Empty; } public virtual Guid Id { get; set; } ... }
In a manual mapping situation, the map would look like the following:
public class CatMap : ClassMap { public CatMap() : base() { this.Id(e => e.Id); ... } }
精彩评论