Archive

Author Archive

RavenDB Inheritance

December 10th, 2011 1 comment

Edit: Updated solution: http://www.philliphaydon.com/2011/12/ravendb-inheritance-revisited/

Continuing my learning of RavenDB, I wanted to see how it handled Inheritance.

I found: http://ravendb.net/faq/polymorphic-indexes

Which showed what to do allow you to select over all types of ‘Animal’ for the example shown. So I wanted to see what happens before and after using this method.

So like the example shown I’ve created an Animal, with a Dog and Cat.

public abstract class Animal
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class Dog : Animal { }
public class Cat : Animal { }

Now if I insert a Dog and Cat:

using (var session = documentStore.OpenSession())
{
    session.Store(new Dog() { Name = "Test Dog" });
    session.Store(new Cat() { Name = "Test Cat" });

    session.SaveChanges();
}

What’s stored in RavenDB is two separate documents, one for ‘dogs’ and one for ‘cats’.

image

If I include the Convention.

var documentConvention =
    new DocumentConvention()
        {
            FindTypeTagName =
                type =>
                    {
                        if (typeof (Animal).IsAssignableFrom(type))
                            return "animals";
                        return DocumentConvention.DefaultTypeTagName(type);
                    }
        };

Note: You can do the conversion when the DocumentStore is initialized, I broke the two up so that it would fit easier into my blog. Otherwise it’s too nested and yucky.

var documentStore =
    (new DocumentStore()
            {
                Url = "http://localhost:8080",
                Conventions = documentConvention
            }).Initialize();

Now when I insert a Dog and Cat I get:

image

Awesome. If we look at the document however:

image

There is no information about it being a cat or dog, I thought it would add some sort of discriminator similar to how NHibernate works.

However, if we look at the Metadata tab:

image

We can see the CLR type is stored in the metadata so RavenDB knows what type to create when we query it.

This means if we query for ‘Animal’ we get a list of Dogs and Cats.

using (var session = documentStore.OpenSession())
{
    var result = session.Query<Animal>();

    foreach (var animal in result)
    {
        Console.WriteLine(animal.Name);
    }
}

 

image

However, if you wanted to query for just Dogs, like so:

var result = session.Query<Dog>().ToList();

It doesn’t seem to work Sad smile

image

I’m probably just doing something wrong, either way, the more I play with RavenDB. The more I love it.

Categories: RavenDB Tags:

Post a collection of ViewModel’s to a MVC Action with jQuery

December 7th, 2011 No comments

Maybe I searched for the wrong thing, but I couldn’t find what I was looking for Sad smile My Bing and Google fu failed me.

Basically I wanted to post a collection of ViewModels to an MCV action. Turns out it’s rather simple.

Lets say I have a bunch of Products, and Products are managed in a WarehouseLocation. A product doesn’t have a warehouse location, since it could exist in multiple locations.

If I’m currently working in Location A, I want to post a collection of Products to an action, as well as the WarehouseLocationId.

So given a simple ViewModel, and an Action:

public class ProductViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

and

public JsonResult Update(int warehouseLocationId, IEnumerable<ProductViewModel> products)
{
    //Do something with the products…

    return Json(new {Staus = "success"});
}

I think usually when someone sends data from jQuery it’s usually a single parameter,so the JSON would look something like:

var data = { id: 1,name: ‘test name’, price: 15.95 };

This would populate an action that looked like:

public JsonResult Update(ProductViewModel product)

But what I was faced with was passing in two parameters, one of which is a collection…

MVC seems to pair up the posted result with the parameter name, in the same way they it does for Route parameters. So to the JSON needs to look like:

var data = {
    warehouseLocationId: 12,
    products: [{
        Id: 1,
        Name: "Product 1",
        Price: 15.95
    }, {
        Id: 3,
        Name: "Product 2",
        Price: 12.50
    }]
};

As you can see the key’s on the first level match the parameter names, while the array on products, match the ViewModel.

Taking this exact data and posting it to the action:

$.ajax({
        type: 'POST',
        url: '@Url.Action("Update", "Home")',
        data: JSON.stringify(data),
        contentType: 'application/json',
        success: function(result) {
            //Do something with result…
        },
        dataType: 'json'
    });

 

I submit that, and with a breakpoint on my action I see:

image

^ The warehouseLocationId…

image

^ 2 products with the values:

image

And:

image

The exact same data we defined in our JavaScript.

The really cool thing about this, is you can have nested collections also. Using the same scenario, but extending Product to have a collection of Categories like so:

public class ProductViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }

    public IEnumerable<Category> Categories { get; set; }
}

public class Category
{
    public int Id { get; set; }
    public string Name { get; set; }
}

I can update the JSON object to include Category information on 1 of the two products:

var data = {
    warehouseLocationId: 12,
    products: [{
        Id: 1,
        Name: "Product 1",
        Price: 15.95
    }, {
        Id: 3,
        Name: "Product 2",
        Price: 12.50,
        Categories: [{
            Id: 1,
            Name: "Category 1"
        }, {
            Id: 1,
            Name: "Category 2"
        }]
    }]
};

And submit that in the same way as before, capturing the results in the Action we get the first product with null for the categories, since we didn’t define it as an empty array:

image

While the second Product has 2 items, the first item is Category 1, and the second item is Category 2.

image

image

And that’s it, easy peasy, sending a collection of ViewModels from jQuery to an MVC Action.

I <3 MVC Smile

Categories: MVC, jQuery Tags: , ,

Split Windows + Web Workbench = Win

November 27th, 2011 No comments

One of the cool features of the Web Workbench from Mindscape is the ability to generate the output files. Prior to using the Web Workbench I was using .LESS{} which uses an HTTP Handler to generate the output files for LESS.

The problem with this is sometimes I would write some CSS and not realise I missed something only to find my site doesn’t display anything, then I have to figure out what I did wrong.

With the Web Workbench, and it’s ability to generate the files every time I save, makes me less error prone.

But the most efficient way of working with it I found (when writing a lot of CSS in 1 sitting) is to split my windows so the first window has where I’m writing, and the second window has the generated CSS file.

image

If I make an error on the left side:

image

I see the error on the right.

If I make a change to the left, (added a background colour) i see the change on the right.

image

This makes it really handy when applying nested rules. Such as nesting a hover rule to an anchor tag. Sometimes I forget to include the colon.

image

Maybe in the next version of the Web Bench, Mindscape can include side-by-side windows that scroll with each other Open-mouthed smile Tho it would be difficult depending on how much CSS was generated. Would still be a nice feature.

Either way, the Web Workbench is a tool that can’t be missed.

Categories: General Tags: , ,

Optional Parameters with AttributeRouting

November 27th, 2011 3 comments

I found a little trick with using Optional Parameters with AttributeRouting, by using standard optional parameters in the action.

The documentation says you can add an attributes to specify the defaults, or add ‘=value’ to the parameter name, and I guess that’s a more correct way to generate routes, but you can achieve the same affect by making the parameter optional. Like so:

[GET("videos/{?page}")]
public ActionResult Videos(int page = 1)
{
    return View("Result");
}

If I browse to the URL:

image

It uses the default value of 1.

image

Now when appending a number to the end of the URL:

image

It captures the correct value:

image

I prefer this method, the optional parameter on the action is more quickly identified, than looking at the attribute to see the defaults. (in my opinion)

Ahh AttributeRouting, how I love you.

Unit of Work with WCF and Autofac

November 6th, 2011 No comments

I’ve just spent the last few days trying to find a way to have a Unit of Work with WCF, but it seems no one has a nice clean easy solution.

The first, and the only decent solution I found was here:

http://ianfnelson.com/archives/2010/04/09/wcf-nhibernate-unit-of-work-endpoint-behavior

The problem I found with this solution is that the ICallContextInitializer as well as the EndpointBehavior is only created once. So it would seem all calls to a service would share the same Unit of Work instance.

Maybe Castle Windsor does something fancy and injects a brand new EndpointBehavior every request to a service, but for me, it seemed the ServiceBehavior, EndpointBehavior, and ICallContextInitializer were all created once.

This caused my service to resolve a different instance of IUnitOfWork to what was in the ICallContextInitializer.

Interim Solution 1

The first solution I came up with was to use Autofac to call Commit on release:

builder.RegisterType(typeof (UnitOfWork))
        .As(typeof (IUnitOfWork))
        .InstancePerLifetimeScope()
        .OnRelease(x =>
                        {
                            ((IUnitOfWork) x).Commit();
                        });

It works… Smile but it seemed like a real hack, so I kept digging.

I posted on StackOverflow & Autofac Google Group, but so far I haven’t had anyone suggest a good solution.

Solution 2

The next took a while to come up with.

Note: I don’t know if this is an appropriate solution for utilizing a Unit of Work with WCF. It works for me but if there is a better solution I would like to hear it.

I started by giving all my classes an interface called IService.

public interface IService
{
    IUnitOfWork UnitOfWork { get; set; }
}

My Service implements this interface:

public class WasteInventoryQueryService : IWasteInventoryQueryService, IService
{
    public IUnitOfWork UnitOfWork { get; set; }
    public IWasteStockRepository WasteStockRepository { get; set; }

    public WasteInventoryQueryService(IUnitOfWork unitOfWork, IWasteStockRepository wasteStockRepository)
    {
        UnitOfWork = unitOfWork;
        WasteStockRepository = wasteStockRepository;
    }

    …
}

Next I created some behaviours similar to the linked article.

Since finding that the ServiceBehavior, EndpointBehavior and ICallContextInitializer all are created once, I started at the ServiceBehavior.

I created a class called EndpointResolverServiceBehavior, it’s purpose is to inject all the endpoint behaviours I create.

public class EndpointResolverServiceBehavior : IServiceBehavior
{
    protected IEnumerable<IEndpointBehavior> EndpointBehaviors { get; set; }

    public EndpointResolverServiceBehavior(IEnumerable<IEndpointBehavior> endpointBehaviors)
    {
        EndpointBehaviors = endpointBehaviors;
    }

    #region Implementation of IServiceBehavior

    public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
    }

    public void AddBindingParameters(ServiceDescription serviceDescription,
        ServiceHostBase serviceHostBase,
        Collection<ServiceEndpoint> endpoints,
        BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
    {
        foreach (var endpoint in serviceDescription.Endpoints)
        {
            foreach (var endpointBehavior in EndpointBehaviors)
            {
                endpoint.Behaviors.Add(endpointBehavior);
            }
        }
    }

    #endregion
}

Next I created an EndpointBehavior called UnitOfWorkEndpointBehavior, it’s purpose is to add the ICallContextInitializer instance.

public class UnitOfWorkEndpointBehavior : IEndpointBehavior
{
    public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
    }

    public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
    }

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
        {
            operation.CallContextInitializers.Add(new UnitOfWorkCallContextInitializer());
        }
    }

    public void Validate(ServiceEndpoint endpoint)
    {
    }
}

And then is the ICallContextInitializer.

public class UnitOfWorkCallContextInitializer : ICallContextInitializer
{
    private PropertyInfo _userObjectInfo;
    private readonly BindingFlags _flags = BindingFlags.NonPublic | BindingFlags.Instance;

    public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
    {
        if (_userObjectInfo == null)
            _userObjectInfo = instanceContext.GetType()
                                                .GetProperty("UserObject", _flags);
            
        return _userObjectInfo.GetValue(instanceContext, null) as IService;
    }

    public void AfterInvoke(object correlationState)
    {
        var uow = correlationState as IService;

        if (uow != null)
            uow.UnitOfWork.Commit();
    }
}

While debugging I found out that the InstanceContext has a private property which has the current service attached to it:

image

image

(click the image for a larger view)

So I reflected the property and casted it to an IService, and return the result. When the service has been invoked, the result passed out of the ‘BeforeInvoke’ method, is passed into the ‘AfterInvoke’.

image

So basically I return the result from the BeforeInvoke which is passed into the AfterInvoke. Then I attempt to cast it to an IService again.

If the cast is successful, then I can call Commit on my UnitOfWork.

The last piece is to wire up the Behavior with Autofac.

builder.RegisterType(typeof(UnitOfWorkEndpointBehavior)).As(typeof(IEndpointBehavior));
builder.RegisterType(typeof(EndpointResolverServiceBehavior)).As(typeof(IServiceBehavior));

Container = builder.Build();

AutofacHostFactory.Container = Container;
AutofacHostFactory.HostConfigurationAction =
    host =>
    {
        host.Description.Behaviors.Add(Container.Resolve<IServiceBehavior>());
    };

And it’s done. I have a working Unit of Work, that is injected into my Service and Committed after the service has been invoked.

The only down-side I see to all of this, is that if an exception is thrown that I don’t capture, then the UoW will still be committed regardless.

If anyone has any better solutions, let me know! Smile

Categories: WCF Tags: , ,

Windows Phone, Windows Live and MSN

November 2nd, 2011 1 comment

Windows Phone 7.5 has been getting some awesome reviews, and rightly so. The thing is amazing. I really think Microsoft has begun leading the way for the mobile platform.

But I’m highly pissed off with the Windows Phone team. Why? Because to use MSN, your msn contacts must be associated with the first live account you register to the phone.

I don’t even know what to say about this, it’s so silly. I understand that it might get confusing to allow multiple Facebook accounts, multiple Windows Live accounts, etc.

But could they not allow you to choose which account MSN contacts are associated to?

When I first setup my phone I didn’t use the Windows Live account I use for MSN (my Hotmail) since it’s existed since 1997, it’s got 100′s of contacts I don’t want in my phone-book, a lot of MSN contacts exist from work, or playing online games, or from forums etc. So I used the Windows Live account that I use for MSDN. I added all my contacts and everything was great, (after I imported all my contacts from outlook into Windows Live Contacts)

I attached my Facebook account, went to People > Settings > Filter Contacts, and turned off Facebook so they do not show in my normal contacts list. This allows me to have normal phone users, but see the Facebook users on the Messaging list.

Now I want to show MSN contacts, so I load up the next Windows Live account, it loads all my contacts, but when I go to messaging, I get NOTHING. No MSN users at all.

On my second Windows Phone (yes I have two) I reformatted it, and signed it up on my Hotmail Windows Live account, and what do I see? All my MSN contacts.

Ok so the team didn’t give us the option to select which Live account we can use for MSN… So I went to download IM+

DEAD END

ATTENTION MSN/WLM users! MSN/WLM is not supported in 1.7 version of IM+ due to Microsoft Marketplace request. If you would like to continue using MSN/WLM in IM+, do not update to 1.7 version from version 1.2. We will continue working on this situation with Microsoft.

WTF… So not only can I not use MSN on my phone natively. The team has blocked anyone else from providing the feature in their own applications…

That’s not fair at all.

Microsoft should be ashamed.

So as it stands, if you don’t use your MSN account as your Windows Phone account, you can’t use MSN.

Microsoft is definitely leading the way in Mobile platform, but they massively screwed up MSN for many users.

Categories: Rant, Windows Phone 7 Tags:

RavenDB – Changing the Lo on the HiLo Generator

October 24th, 2011 2 comments

Well I’m currently learning RavenDB, it’s awesome! But I noticed when I put data in, all the Id’s generated every time I ran up my application to test were:

1, 2, 3, 4, 5…

1024, 1025, 1026, 1027, 1028…

2048, 2049, 2050, 2051, 2052…

This would be fine after the app is deployed since I wouldn’t be restarting it over and over and over, but during development I personally find it annoying that the numbers jump so high.

Fortunately I figured out a way. (which about an hour later I found on Google Groups, granted I had to use a different keyword to find it)

Basically you just need to create a new instance of the MultiTypeHiLoKeyGenerator class, passing in the arguments and assigning it to the document store:

var documentStore = new DocumentStore { Url = "http://localhost:12321/" };
documentStore.Initialize();

var generator = new MultiTypeHiLoKeyGenerator(documentStore, 10);
documentStore.Conventions.DocumentKeyGenerator =
    entity => generator.GenerateDocumentKey(documentStore.Conventions, entity);

using (var session = documentStore.OpenSession())
{
    session.Store(new Project() { Title = "Hello World" });
    session.SaveChanges();
}

So running up my app once:

image

And again:

image

Now the identity only increases every time the app restarts. And to show it generates more than 1 number…

image

It took a while of hunting on the net, but it turns out Googling & Binging, or searching(StackOverflow/Google Groups) for the keyword ‘Lo’ doesn’t work, the argument is ‘capacity’ and searching for that on Google Groups lead me here:

http://groups.google.com/group/ravendb/…..q=capacity

Hopefully someone else finds this useful Smile

Categories: RavenDB Tags: , , , ,

NHibernate Designer 2

October 20th, 2011 No comments

The guys at MindScape have released their next version of NHibernate Designer, which now supports Fluent NHibernate and a whole heap of new features.

They also dropped the price down to just $99!

I recommend checking it out

http://www.mindscapehq.com/blog/index.php/2011/10/19/nhibernate-designer-2-is-here/

http://www.mindscapehq.com/products/nhdesigner

Categories: Fluent NHibernate, NHibernate Tags:

Website Folder Structure? CSS Files? Does anyone care? I do…

October 17th, 2011 2 comments

When we build website’s, more often than not we have: Separation of Concerns. Even if at most it’s just basic 3-tier Architecture

What annoys me though is a lot of time no one ever thinks about separation of concerns when it comes to the folder structure of their website, and where things go.

Folders

The one thing that annoys me above all else, is when ‘layout images’ (images for layout, design, styling etc) of the website, are shoved into the same folder that holds what I call “Content Images”.

For example:

root/
root/css/
root/images/

What I prefer to do is structure it so the css folder has it’s own images folder, specifically for layout images.

root/
root/css/
root/css/images/
root/images

To take it a step further, I often have images, icons, and fonts.

root/
root/css/
root/css/fonts/
root/css/icons/
root/css/images/
root/images

This way I don’t have to worry about finding specific icons in a folder full of images, I don’t have to worry about sifting through images to find ones related to the layout/design, they are all neatly tucked away in their own specific areas.

When it comes to folder structure however, NuGet gets in the way.

It would be nice if it allowed you to specify where file types should go. At the moment ‘css’ files seem to go into ‘Content’. JavaScript files go into ‘Scripts’. But what I would rather have is all lower-case names, and ‘css’ rather than ‘content’. Until then, I just download those sort of dependencies manually and create my own folder structure.

CSS

The next thing that I find annoying is the God Style Sheet. It’s the StyleSheet that people name:

Styles.css

It’s the only one that exists in the project, it’s over 100k in size, no comments, no christmas trees. Just lines and lines of fail.

The approach I used to take (before finding .LESS) was creating multiple StyleSheets that were small and easy to maintain, sometimes I would end up with up to 12, possibly more depending on the size of the website.

Each StyleSheet would be responsible for a specific task, so I would have something like the following:

/css/reset.css (this is just one of those many reset StyleSheets found on the net)
/css/layout.css
/css/main.css
/css/header.css
/css/footer.css
/css/main-navigation.css
/css/…

When sections of the website were broken down like this, it did require flicking between StyleSheets now-n-then, but they became much smaller and easier to maintain. I also became far-less at risk of Unwanted Side Effects.

Now with .LESS and LESS, it’s easy to have only a few StyleSheets, since now you can tab within a specific region and continue to write styles that only apply to that region.

For example, given a Footer element. You could come up with something like:

footer {
    border-top: 2px #182a33 solid;
    padding-top: 30px;
    nav {
        a {
            font-family: @footer-link-font;
            font-size: @footer-link-size;
            color: @footer-link-color;
            text-decoration: none;
            &:hover {
                color: @footer-link-color-hover;
                text-decoration: underline;
            }    
        }
        li > span {
            color: @footer-text-color;
            font-family: @footer-text-font;
            font-size: @footer-text-size;
        }
        h4 {
            color: @footer-heading-color;
            font-family: @footer-heading-font;
            font-size: @footer-heading-size;
            font-weight: bold;
            margin-bottom: 35px;
            padding-top: 17px;
        }
        > ul > li {
            width: 165px;
            float: left;
            display: block;
            line-height: 18px;
        }
    }
}

This would in turn generate the following CSS for you.

footer {
  border-top: 2px #182a33 solid;
  padding-top: 30px;
}
footer nav a {
  font-family: arial;
  font-size: 12px;
  color: #00adee;
  text-decoration: none;
}
footer nav a:hover {
  color: #00adee;
  text-decoration: underline;
}
footer nav li > span {
  color: #a8a8a8;
  font-family: arial;
  font-size: 12px;
}
footer nav h4 {
  color: white;
  font-family: arial;
  font-size: 16px;
  font-weight: bold;
  margin-bottom: 35px;
  padding-top: 17px;
}
footer nav > ul > li {
  width: 165px;
  float: left;
  display: block;
  line-height: 18px;
}

I find it much easier to manage writing ‘LESS’ then traditional CSS.

Conclusion

I didn’t want to go into too much detail, my main point is I think people should put a little more thought into how they structure their folders, files, naming, etc when creating websites. We focus so much time on trying to main our applications and code maintainable, but somehow neglect the website itself, and after a while we just end up fighting with it.

The benefits of letting the ORM generate the Identity (part 1)

September 22nd, 2011 No comments

One thing I’ve learnt is that letting the database generate the identity for you is a bad thing. It always annoyed me that Oracle never gave a feature like AUTO_INCREMENT in MySQL or IDENTITY in SQL Server. I never understood, when inserting data how do I give it an Id?

Well one of the benefits of ORMs such as NHibernate is we can generate the identity our-self, or rather, the ORM can generate it so we don’t rely on the database. This also plays a major part in our code base when we insert a graph or batch of data and how the identity is added to our object.

Ayende recommend avoiding identity.

The thing with using SQL Server”s identity is that we need to select the identity back out after we do an insert. Not only that, when using NEWID()/NEWSEQUENTIALID() there is no way to select the value back other than using all the fields in a select in order to get the GUID relates to the record with all those values matching.

For example:

Given this rather simple table using IDENTITY.

CREATE TABLE People
(
    Id int NOT NULL IDENTITY (1, 1) PRIMARY KEY,
    FirstName nvarchar(100) NOT NULL,
    Surname nvarchar(100) NOT NULL
)

And I’ll demo with NEWID() as well.

CREATE TABLE Fruit
(
    Id uniqueidentifier NOT NULL PRIMARY KEY DEFAULT (NEWID()),
    Name nvarchar(100) NOT NULL
)

Note: I’m unaware of anyway to get NHibernate to use NEWSEQUENTIALID()

We map these in NHibernate like so:

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Table("People");
        Id(x => x.Id).GeneratedBy.Identity();

        Map(x => x.FirstName);
        Map(x => x.Surname);
    }
}

public class FruitMap : ClassMap<Fruit>
{
    public FruitMap()
    {
        Table("Fruit");
        Id(x => x.Id).GeneratedBy.GuidNative();

        Map(x => x.Name);
    }
}

If we insert data into People and Fruit like so:

using (var tx = session.BeginTransaction())
{
    var person = new Person
                        {
                            FirstName = "Phillip",
                            Surname = "Haydon"
                        };

    var fruit = new Fruit
                    {
                        Name = "Apple"
                    };

    session.SaveOrUpdate(person);
    session.SaveOrUpdate(fruit);

    tx.Commit();
}

We get the following statement’s run:

– statement #1
begin transaction with isolation level: Unspecified

– statement #2
INSERT INTO People
            (FirstName,
             Surname)
VALUES      ('Phillip' /* @p0 */,
             'Haydon' /* @p1 */);

select SCOPE_IDENTITY()

– statement #3
select newid()

– statement #4
INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple' /* @p0 */,
             '3411c820-f9cc-4385-97a1-31cf7e7c612c' /* @p1 */)

– statement #5
commit transaction

What’s interesting is for the Identity, we have to select the SCOPE_IDENTITY() back after the insert so that we can populate the Person object, and for the Fruit object, we have to select NEWID() first as a separate statement, then add it to the business object, and commit it.

This round-trip to the database in order to get the GUID first before doing the insert is completely unnecessary, not to mention has a performance impact.

Inserting 50,000 items for each, with the batch-size set to 50, yields the following:

IDENTITY 28951
NEWID 30241

(value in milliseconds)

Note: These benchmarks are quick-nasty benchmarks and were only run once.

The interesting thing is neither IDENTITY or NEWID batched any of the insert statements together, they were all issued as separate statements.

(re-run the test inserting 3 to show SQL output)

The ‘Person’ insert looks like this:

– statement #1
begin transaction with isolation level: Unspecified

– statement #2
INSERT INTO People
            (FirstName,
             Surname)
VALUES      ('Phillip0' /* @p0 */,
             'Haydon' /* @p1 */);

select SCOPE_IDENTITY()

– statement #3
INSERT INTO People
            (FirstName,
             Surname)
VALUES      ('Phillip1' /* @p0 */,
             'Haydon' /* @p1 */);

select SCOPE_IDENTITY()

– statement #4
INSERT INTO People
            (FirstName,
             Surname)
VALUES      ('Phillip2' /* @p0 */,
             'Haydon' /* @p1 */);
             
select SCOPE_IDENTITY()

– statement #5
commit transaction

Each insert has to be done 1 by 1, since it needs to select the identity back.

The ‘Fruit’ table on the other hand:

– statement #1
begin transaction with isolation level: Unspecified

– statement #2
select newid()

– statement #3
select newid()

– statement #4
select newid()

– statement #5
INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple0' /* @p0_0 */,
             '269bc638-74b4-4568-85d1-45b6e537fcbd' /* @p1_0 */)

INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple1' /* @p0_1 */,
             'fc848779-b173-4c31-b8b6-0a7735c0c2dc' /* @p1_1 */)

INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple2' /* @p0_2 */,
             '232c8971-18c7-486d-9152-26c969c3b632' /* @p1_2 */)

– statement #6
commit transaction

It select 50,000 GUIDs first, then it issues all the insert statement’s in batches of 50.

Now lets look at HiLo and GuidComb (GuidComb is a Sequencial Guid, but NH also allows normal Guids), two ways of generating identities in the ORM rather than the database.

The tables are the same as before, except they don’t have ‘IDENTITY’ or a Default Value.

The mappings have been updated to:

Id(x => x.Id).GeneratedBy.HiLo("100");

And

Id(x => x.Id).GeneratedBy.GuidComb();

Running a single insert for both results in:

– statement #1
begin transaction with isolation level: Unspecified

– statement #2
Reading high value:
select next_hi
from   hibernate_unique_key with (updlock, rowlock)

– statement #3
Updating high value:
update hibernate_unique_key
set    next_hi = 2 /* @p0 */
where  next_hi = 1 /* @p1 */

– statement #4
INSERT INTO People
            (FirstName,
             Surname,
             Id)
VALUES      ('Phillip' /* @p0_0 */,
             'Haydon' /* @p1_0 */,
             101 /* @p2_0 */)

– statement #5
INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple' /* @p0_0 */,
             '3229618e-bd8a-45ae-8ad5-9f660016980d' /* @p1_0 */)

– statement #6
commit transaction

Besides NHibernate getting the first Hi value for use in the HiLo algorithm, both insert statement did not require selecting or generating any identity, it was all done in NHibernate.

This makes inserting 3 ‘Person’ much more efficient:

– statement #1
begin transaction with isolation level: Unspecified

– statement #2
Reading high value:
select next_hi
from   hibernate_unique_key with (updlock, rowlock)

– statement #3
Updating high value:
update hibernate_unique_key
set    next_hi = 3 /* @p0 */
where  next_hi = 2 /* @p1 */

– statement #4
INSERT INTO People
            (FirstName,
             Surname,
             Id)
VALUES      ('Phillip0' /* @p0_0 */,
             'Haydon' /* @p1_0 */,
             202 /* @p2_0 */)

INSERT INTO People
            (FirstName,
             Surname,
             Id)
VALUES      ('Phillip1' /* @p0_1 */,
             'Haydon' /* @p1_1 */,
             203 /* @p2_1 */)

INSERT INTO People
            (FirstName,
             Surname,
             Id)
VALUES      ('Phillip2' /* @p0_2 */,
             'Haydon' /* @p1_2 */,
             204 /* @p2_2 */)

– statement #5
commit transaction

3 insert’s done as a single batch statement.

And inserting 3 Fruit:

– statement #1
begin transaction with isolation level: Unspecified

– statement #2
INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple0' /* @p0_0 */,
             'db902160-edbb-49c7-bf52-9f660018299a' /* @p1_0 */)

INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple1' /* @p0_1 */,
             '5e852528-3a6f-41d2-a6b1-9f660018299a' /* @p1_1 */)

INSERT INTO Fruit
            (Name,
             Id)
VALUES      ('Apple2' /* @p0_2 */,
             '2f63c6e8-e595-4393-ad15-9f660018299a' /* @p1_2 */)

– statement #3
commit transaction

Again, 3 insert’s done as a single batch statement.

If we run 50,000 inserts again:

HiLo 9287
GuidComb 9060

That is over 3 times faster!

So as you can see, for just doing batch inserting, with a full Session (rather than stateless) and allowing the ORM to generate identities, we can significantly improve performance.