NHibernate Id Generator With Suffix

I had recently the need for using an id generator with two requirements:

  • Is DB-independent
  • Allows data generated in different sites (DBs) to be merged into a centralized DB

I already knew about HiLo generator, and it seemed fine, except that the generated ids, on different sites, would most probably clash, unless I would setup a particular configuration leaving lots of room, and would constantly monitor its usage. So I decided to adapt it: I basically pick the generator produced by the HiLo generator, and add my own suffix to it, obtained from the configuration file, where the suffix is different for each site. Very simple, here it is:

public class HiLoWithSuffixIdGenerator : TableHiLoGenerator
	public const String NodeSuffixAppSettingsKey = "NodeSuffix";
	protected static Int32 nodeSuffix  = 0;
	static HiLoWithSuffixIdGenerator()
	 	//try to read the node suffix from the application settings
		if (Int32.TryParse(ConfigurationManager.AppSettings[NodeSuffixAppSettingsKey],  out nodeSuffix) == false)
			//the node suffix key does not exist or is not a number
			throw new ApplicationException(String.Format("Application settings does not contain key {0} or it is not a number.", NodeSuffixAppSettingsKey));
	public override void Configure(IType type, IDictionary<String, String> parms, Dialect dialect)
		//extract some parameter here, if needed
		//Int32 someProperty = PropertiesHelper.GetInt32("SomeProperty", parms, 0);
		base.Configure(type, parms, dialect);

	public override Object Generate(ISessionImplementor session, Object obj)
		//1 - get id using standard HiLo algorithm
		Int64 baseId = (Int64) base.Generate(session, obj);
		//2 - shift id to the left, leaving room for 3-digit node suffixes
		baseId *= 1000;
		//3 - combine id with the node suffix
		baseId += nodeSuffix;

		return (baseId);

It can be configured fluently:

public class CustomerMap : ClassMap<Customer>
	public CustomerMap()
		this.Id(c => c.Id).Column("ID").GeneratedBy.Custom<HiLoWithSuffixIdGenerator>();
		this.Map(c => c.Name).Column("NAME").Not.Nullable();
		this.Map(c => c.Address).Column("ADDRESS").Not.Nullable().LazyLoad();
		this.HasMany<Order>(c => c.Orders).KeyColumn("CUSTOMERID").Inverse().AsSet().Cascade.All().Fetch.Join();

Or through .hbm.xml:

<class name="Customer">
    <id name="Id">
      <generator class="HiLoWithSuffixIdGenerator">

Simple, don't you think?

Bookmark and Share


No Comments