开发者

NHibernate ID generator when using NServiceBus

For most CRUD apps I use NHibernate's guid.comb ID generator. This has the advantage that I have access to the ID before I flush to the database and gets around the index fragmentation issue associated with using normal Guids.

When we introduce messaging it raises a few questions:

  1. Since we are sending commands to make changes to our domain layer, we don't 开发者_如何学Cactually have access to the "new" domain object in the UI. Often (in the case of a web application) we need it's identifier to redirect to another page. One solution would be to pass the id as part of the command (e.g. Guid.NewGuid()) but then we lose the sequential Guids that NHibernate provides.
  2. If we instead use an identity strategy we remove the index issue but now have no easy way of determining the id from the UI, other than subscribing to an event or executing he command synchronously, both of which are not ideal in a web application.

So I'm curious what strategy other NServiceBus developers are taking. Performing some operation on an existing entity is not really a problem since we can just send a request using ajax to dispatch the command, and notify the user that everything was successful (probably). Since the page they are on already has the updated information this is enough.

However when we create a new instance of a domain object (via a command) we often need to redirect the user to a page that then retrieves the newly created entity from our database. Of course this entity may not have been saved yet (as we are processing our commands async) and we typically need an Id to perform this redirect.


This is the code that nhibernate uses to generate a comb.

private Guid Generate()
    {
        byte[] guidArray = Guid.NewGuid().ToByteArray();

        DateTime baseDate = new DateTime(1900, 1, 1);
        DateTime now = DateTime.Now;

        // Get the days and milliseconds which will be used to build the byte string 
        TimeSpan days = new TimeSpan(now.Ticks - baseDate.Ticks);
        TimeSpan msecs = now.TimeOfDay;

        // Convert to a byte array 
        // SQL Server is accurate to 1/300th of a millisecond so we divide by 3.333333 
        byte[] daysArray = BitConverter.GetBytes(days.Days);
        byte[] msecsArray = BitConverter.GetBytes((long)(msecs.TotalMilliseconds / 3.333333));

        // Reverse the bytes to match SQL Servers ordering 
        Array.Reverse(daysArray);
        Array.Reverse(msecsArray);

        // Copy the bytes into the guid 
        Array.Copy(daysArray, daysArray.Length - 2, guidArray, guidArray.Length - 6, 2);
        Array.Copy(msecsArray, msecsArray.Length - 4, guidArray, guidArray.Length - 4, 4);

        return new Guid(guidArray);
    }

Maybe you can use it :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜