Logo

NHibernate

The object-relational mapper for .NET

How to

This page is converted from the old nhforge.org Wiki. Published by: Ricardo Peres on 03-31-2011

HiLo Generator With Node Suffix

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

 

  • Is DB-independent
  • Allows data generated in different 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, where the suffix is different for each site. Very simple, here it is:

 

public class CustomIdGenerator : TableHiLoGenerator
{
	public const String NodeSuffixAppSettingsKey = "NodeSuffix";
 
	protected static Int32 nodeSuffix  = 0;
 
	static CustomIdGenerator()
	{
	 	//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 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<CustomIdGenerator>();
		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" table="`CUSTOMER`">
    <id name="Id" column="ID" type="long">
      <generator class="CustomIdGenerator, CustomIdGeneratorAssembly">
      </generator>
    </id>
© NHibernate Community 2024