【问题标题】:What are the different GeneratedBy's in nhibernate/fluent nhibernate在 nhibernate/fluent nhibernate 中有什么不同的 GeneratedBy
【发布时间】:2011-09-14 16:25:43
【问题描述】:

我正在玩 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();

nhibernate 会自动为我生成一个 ID(如果我使用 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,这使您需要更大的数据类型。

【问题讨论】:

    标签: nhibernate fluent-nhibernate


    【解决方案1】:

    请参阅NHibernate Docs 了解各种生成器。 IMO GUID(Comb) 或 HiLo 具有最佳性能,因为可以在应用程序中生成 Id。如果您使用 HiLo,您可以轻松切换到没有该功能的 ORM,只需使用 value > max(Id) 创建一个序列并将其用作列的默认值来模拟自动增量。

    注意:在我的项目中,我总是成功地使用 HiLo,所以我有偏见。

    【讨论】:

    • 嗯,我正在考虑使用 GUID,因为这似乎也是一个好方法。唯一的问题是它们看起来很丑(并且不确定是否应该在 url 中使用它们。我猜测需要某种解决方案)。
    • hilo 生成具有可读性的整数/长整数。或者您使用本机但您必须更改表以使用自动 ID(不知道它在 SQLServer 中是如何调用的)。
    【解决方案2】:

    MSSQL 本机使用自动标识。您需要在 ID 列上打开自动标识以便 NHibernate 插入。

    查看另一篇关于不使用身份生成器的文章:http://ayende.com/blog/3915/nhibernate-avoid-identity-generator-when-possible

    【讨论】:

      【解决方案3】:
      "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,您几乎必须让数据库提供某种同步。

      如果选择Identity,如果需要Id,则必须在插入后立即调用scope_identity()。而且由于 NHibernate 总是需要你 session.Save() 的实体的 ID,它会这样做。

      【讨论】:

        猜你喜欢
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2011-04-10
        • 1970-01-01
        • 1970-01-01
        • 2011-02-01
        • 1970-01-01
        • 2010-10-17
        相关资源
        最近更新 更多