Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6745933
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 26, 20262026-05-26T12:15:47+00:00 2026-05-26T12:15:47+00:00

It looks like NH gets MAX(ID) only once, at first insert and then stores

  • 0

It looks like NH gets MAX(ID) only once, at first insert and then stores this value internally, this causes me some problems when other processes inserts data. Then I have not actual ID and duplicate key exception is thrown.

Lets imagine we have table Cats

CREATE TABLE Cats(ID int, Name varchar(25))

Then we have corresponding mapping done with FluentNhibernate

public class CatMap : ClassMap<Cat>
{
    public CatMap()
    {
      Id(m=>m.ID).GeneratedBy.Increment();
      Map(m=>.Name);
    }
}

All I want to achieve is to insert my Cat records with ID’s generated by NHibernate using SELECT MAX(ID) FROM Cats before any insert. Executing Session.Flush after any commit dosnt work. I’v done some investigation using SQL Server profiler, and this sql stetement is executed only once (at first insert) – other inserts doesnt force to retreive actual MAX(ID). I know that other algorithms like HiLo are better, but I cant replace it.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-26T12:15:48+00:00Added an answer on May 26, 2026 at 12:15 pm

    As you found out, the NHibernate Increment id generator was not intended for use in a multi-user environment. You state that using a HiLo generator is not an option so you’re left with these options:

    • use the Native generator and change the id column to use the database supported identity mechanism

    • use the Assigned generator and write code to determine the next valid id

    • create a Custom generator where you implement the IIdentifierGenerator interface to do what you need

    Below is sample code for a custom generator that uses a generalized proc to get an ID for a given table. The main issue with this approach is that you must wrap the code in something like a Unit of Work pattern to ensure the ‘select max(id) …” and the insert are covered by the same database transaction. The IIdentifierGenerator link has the XML mapping you need to wire up this custom generator.

    using System;
    using System.Collections.Generic;
    using System.Data;
    using NHibernate.Dialect;
    using NHibernate.Engine;
    using NHibernate.Id;
    using NHibernate.Persister.Entity;
    using NHibernate.Type;
    
    namespace YourCompany.Stuff
    {
        public class IdGenerator : IIdentifierGenerator, IConfigurable
        {
            private string _tableName;
            // The "select max(id) ..." query will go into this proc:
            private const string DefaultProcedureName = "dbo.getId";
    
            public string ProcedureName { get; protected set; }
            public string TableNameParameter { get; protected set; }
            public string OutputParameter { get; protected set; }
    
            public IdGenerator()
            {
                ProcedureName = DefaultProcedureName;
                TableNameParameter = "@tableName";
                OutputParameter = "@newID";
            }
    
            public object Generate(ISessionImplementor session, object obj)
            {
                int newId;
                using (var command = session.Connection.CreateCommand())
                {
                    var tableName = GetTableName(session, obj.GetType());
    
                    command.CommandType = CommandType.StoredProcedure;
                    command.CommandText = ProcedureName;
    
                    // Set input parameters
                    var parm = command.CreateParameter();
                    parm.Value = tableName;
                    parm.ParameterName = TableNameParameter;
                    parm.DbType = DbType.String;
    
                    command.Parameters.Add(parm);
    
                    // Set output parameter
                    var outputParameter = command.CreateParameter();
                    outputParameter.Direction = ParameterDirection.Output;
                    outputParameter.ParameterName = OutputParameter;
                    outputParameter.DbType = DbType.Int32;
    
                    command.Parameters.Add(outputParameter);
    
                    // Execute the stored procedure
                    command.ExecuteNonQuery();
    
                    var id = (IDbDataParameter)command.Parameters[OutputParameter];
    
                    newId = int.Parse(id.Value.ToString());
    
                    if (newId < 1)
                        throw new InvalidOperationException(
                            string.Format("Could not retrieve a new ID with proc {0} for table {1}",
                                          ProcedureName,
                                          tableName));
                }
    
                return newId;
            }
    
            public void Configure(IType type, IDictionary<string, string> parms, Dialect dialect)
            {
                _tableName = parms["TableName"];
            }
    
            private string GetTableName(ISessionImplementor session, Type objectType)
            {
                if (string.IsNullOrEmpty(_tableName))
                {
                    //Not set by configuration, default to the mapped table of the actual type from runtime object:
                    var persister = (IJoinable)session.Factory.GetClassMetadata(objectType);
    
                    var qualifiedTableName = persister.TableName.Split('.');
                    _tableName = qualifiedTableName[qualifiedTableName.GetUpperBound(0)]; //Get last string
                }
    
                return _tableName;
            }
        }
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Looks like my only option is to create a mutatant child of the tree
It looks like we'll be adding CAPTCHA support to Stack Overflow. This is necessary
Let's say I have a class that looks something like this: class Foo(Prop1:Int, Prop2:Int,
I have a JAVASCRIPT array that looks like this: postarray['min_price'] = 120000; postarray['max_price'] =
Looks like here in StackOveflow there is a group of F# enthusiasts. I'd like
Looks like while( condition ) { //do stuff } is completely equivalent to for(
Looks like ExpressionTrees compiler should be near with the C# spec in many behaviors,
Looks like there is no Load event for usercontrol on the CF. I'm used
Looks like XSD.exe is not delivered as a part of Visual Studio 2010. what
Looks like dynamic memory allocation without garbage collection is a way to disaster. Dangling

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.