我正在玩nhibernate和流利的nhibernate并且看着GeneratedBy并且有很多选择(sequence,sequenceIdentity等),但我不知道他们大多数人做了什么。
我看到例如3个Guid。
GeneratedBy.Guid();
GeneratedBy.GuidComb();
GeneratedBy.GuidNative();
我听说不使用Guid()并使用GuidComb,因为它是专为处理数据库而设计的(它不会破坏索引)。
我不知道GuidNative()
是什么。
我也试图制作
GeneratedBy.Native()
我认为这会使用MSSQl 2008使用的任何东西,但我遇到了它的问题
CREATE TABLE [dbo].[AutoIds](
[Id] [int] NOT NULL,
[Test] [varchar](50) NULL,
CONSTRAINT [PK_AutoIds] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
我想通过做
Id(x => x.Id).GeneratedBy.Native();
我会自动为我生成一个id由nhibernate生成(如果我使用combGuid()就会这样做)但是当我尝试提交它时我得到了
NHibernate.Exceptions.GenericADOException was caught
Message=could not insert: [unitofwork.Models.Domain.AutoIds][SQL: INSERT INTO [AutoIds] (Test) VALUES (?); select SCOPE_IDENTITY()]
Source=NHibernate
SqlString=INSERT INTO [AutoIds] (Test) VALUES (?); select SCOPE_IDENTITY()
StackTrace:
at NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Boolean[] notNull, SqlCommandInfo sql, Object obj, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object[] fields, Object obj, ISessionImplementor session)
at NHibernate.Action.EntityIdentityInsertAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSaveOrReplicate(Object entity, EntityKey key, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.PerformSave(Object entity, Object id, IEntityPersister persister, Boolean useIdentityColumn, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.AbstractSaveEventListener.SaveWithGeneratedId(Object entity, String entityName, Object anything, IEventSource source, Boolean requiresImmediateIdAccess)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.SaveWithGeneratedOrRequestedId(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.EntityIsTransient(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveEventListener.PerformSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Event.Default.DefaultSaveOrUpdateEventListener.OnSaveOrUpdate(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.FireSave(SaveOrUpdateEvent event)
at NHibernate.Impl.SessionImpl.Save(Object obj)
at unitofwork.Models.Repository.StoreRepo.Create(AutoIds autoIds) in StoreRepo.cs:line 37
at unitofwork.Models.Service.StoreService.CreateStore() inStoreService.cs:line 40
InnerException: System.Data.SqlClient.SqlException
Message=Cannot insert the value NULL into column 'Id', table 'TESTUoW.dbo.AutoIds'; column does not allow nulls. INSERT fails.
The statement has been terminated.
Source=.Net SqlClient Data Provider
ErrorCode=-2146232060
Class=16
LineNumber=1
Number=515
Procedure=""
Server=(local)
State=2
StackTrace:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
at System.Data.SqlClient.SqlDataReader.get_MetaData()
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
at System.Data.SqlClient.SqlCommand.ExecuteReader(CommandBehavior behavior, String method)
at System.Data.SqlClient.SqlCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader()
at NHibernate.AdoNet.AbstractBatcher.ExecuteReader(IDbCommand cmd)
at NHibernate.Id.IdentityGenerator.InsertSelectDelegate.ExecuteAndExtract(IDbCommand insert, ISessionImplementor session)
at NHibernate.Id.Insert.AbstractReturningDelegate.PerformInsert(SqlCommandInfo insertSQL, ISessionImplementor session, IBinder binder)
InnerException:
nhibernate可以不自动递增整数吗?这只是一件难以跟踪的事情,以便找出下一个数字吗?
我正在玩ids,因为我很震惊地得知我这样做的方式不是一个好方法(我在我的数据库中设置为自动递增int,这就像我一直为ado.net做的那样和linq到sql)。
每次执行保存时,都会发生对数据库的额外查询(获取pk)。所以我正在四处寻找导致这种情况发生的组合。
我开始更倾向于使用Guid(即使我更喜欢使用更短的内容,因此如果你出于某种原因需要手动查看数据库,那么在其他表中匹配会更快)。
我在考虑hilo,但我不喜欢的是,如果我必须切换ORM来说实体框架可能不支持hilo。再加上我听说使用HiLO,它可以很快地通过大量的id,使你需要更大的数据类型。
答案 0 :(得分:2)
请参阅NHibernate Docs了解各种生成器。 IMO GUID(Comb)或HiLo具有最佳性能,因为可以在应用程序中生成ID。如果您使用HiLo,您可以轻松切换到没有该功能的ORM,只需创建一个value > max(Id)
的序列,并将其用作列的默认值来模拟自动增量。
注意:在我的项目中,我总是使用HiLo成功,所以我有偏见。
答案 1 :(得分:1)
MSSQL native使用自动标识。您需要在ID列上打开自动标识以便NHibernate插入。
查看另一篇关于不使用身份生成器的文章:http://ayende.com/blog/3915/nhibernate-avoid-identity-generator-when-possible
答案 2 :(得分:0)
"Can nhibernate not do auto incrementing ints? Is that just something too hard to keep track of for it to figure out the next number?"
当您有两个应用程序实例访问数据库时,这将无效。
使用整数Id,您几乎必须让db提供某种同步。
如果选择Identity,则必须在插入后立即调用scope_identity(),如果需要Id。而且由于NHibernate总是需要为session.Save()实体提供Id,所以它就是这样做的。