Wednesday, June 17, 2009

Domain Events pattern in NCommon

Steve Gentile recently directed me to Udi Dahan’s recent post his improvement on the Domain Event pattern, and after reading the post, digesting it and thinking about his approach I have decided to include it into NCommon.

The Domain Event pattern aims to provide a solution for being able to create fully encapsulated domain models. The term fully encapsulated domain models refer to the approach where the entities in your domain model are not bound or depend on external services for any purpose or operation.

A good example for this, although a beaten to death example, is the email sending or rather the notification example. Lets say when an order’s status has changed an email notification has to be sent out to the customer of the order informing them of this status change. My previous approach has been to use the Service Locator pattern to get a service instance of IOrderStatsNotifier and use the IOrderStatusNotifier instance to send out the emails.

Semantically that has always bothered me because the domain entity really should not be informing the notifier that the order’s status has changed, rather it should be the other way around. The Notifier should automatically be able to handle order’s status change and do the necessary. With the Domain Events pattern this becomes ridiculously easy.

If you haven’t read Udi’s post, I’d strongly recommend reading it. Anyways, the implementation of Domain Events pattern in NCommon is almost identical to that shown in Udi’s post. Below is a test from NCommon that shows how the Domain Event pattern can be used:

[Test]

public void registered_handlers_are_executed_when_event_is_raised ()

{

    var mockTest1Handler = MockRepository.GenerateMock<Handles<TestEvent1>>();

    var mockTest2Handler = MockRepository.GenerateMock<Handles<TestEvent2>>();

    var locator = MockRepository.GenerateStub<IServiceLocator>();

 

    locator.Expect(x => x.GetAllInstances<Handles<TestEvent1>>())

           .Return(new[]{mockTest1Handler});

 

    ServiceLocator.SetLocatorProvider(() => locator);

 

    DomainEvent.Raise(new TestEvent1());

    mockTest1Handler.AssertWasCalled(x => x.Handle(null), options => options.IgnoreArguments());

    mockTest2Handler.AssertWasNotCalled(x => x.Handle(null), options => options.IgnoreArguments());

}

The implementation of Domain Events pattern is available in trunk.

Submit this story to DotNetKicks

Friday, May 15, 2009

FluentNHibernate Mappings: Any

Recently Oren (Ayende) had a serious of posts on NHibernate mappings and the various options you can configure using Xml mappings. This series of posts takes those examples and shows how you can use FluentNHibernate to configure the same mappings.

This is a companion post for Oren’s post on the <any> mapping in NHibernate, here. I recommend reading his post before venturing forward.

In Fluent NHibernate you can use the ReferencesAny mapping method to output a <any> mapping:

ReferencesAny(mapping => mapping.Payment)

    .EntityTypeColumn("PaymentType")

    .EntityIdentifierColumn("PaymentId")

    .AddMetaValue<CreditCardPayment>("Credit")

    .AddMetaValue<CheckPayment>("Check")

    .IdentityType(identity => typeof(int));

Note: This mapping method at this time is generating the <any> mapping incorrectly. The mapping that is being generated contains <any> before the <Id> element causing NHibernate to complain. I've submitted a patch to fix this behavior, which you can get from here: http://code.google.com/p/fluent-nhibernate/issues/detail?id=228

Note2: ReferencesAny is available in the latest trunk as support for it was added fairly recently. So if you can't seem to find it in the fluent-nhibernate.dll build you are using, get latest from trunk and build it.

The ReferencesAny prety much matches the <any> element. You specify the meta values using the AddMetaValue method, the type column via EntityTypeColumn and the identity column using the EntityIdentifierColumn method.

Submit this story to DotNetKicks

Thursday, May 14, 2009

FluentNHibernate Mappings: Join

Recently Oren (Ayende) had a serious of posts on NHibernate mappings and the various options you can configure using Xml mappings. This series of posts takes those examples and shows how you can use FluentNHibernate to configure the same mappings.

This is a companion post for Oren’s post on the <join> mapping in NHibernate, here. I recommend reading his post before venturing forward.

To create a joined table mapping using FluentNHibernate you need to use the WithTable mapping function and specify the JoinedPart definition:

WithTable("Addresses", join =>

                           {

                               join.Map(prop => prop.StreetAddress1, "StreetAddress1");

                            join.Map(prop => prop.StreetAddress2, "StreetAddress2");

                            join.Map(prop => prop.City, "City");

                            join.Map(prop => prop.State, "State");

                            join.Map(prop => prop.ZipCode, "ZipCode");

                               join.WithKeyColumn("PersonId");

                           });

The WithTable mapping function has two overloads, one just taking in a string parameter and another that takes in a string parameter as well as a action that allows you to configure a JoinPart. The first overload instructs fluent nhibernate to output the table name of the class being mapped, for e.g WithTable("Persons") will generate a mapping: <class name="Person" table="Persons"> element.

The second overload outputs the <join> element in the mapping. Just like mapping a component, the JoinPart allows you to map properties in the class as belonging to another table. The only thing to be aware of here is that you are specifying the column names in the join table for your properties manually.

Now to define the join table as optional, you again need to use the SetAttribute method to output the "optional" attribute since there's no inbuilt way to specify that in the JoinPart. Below is the full mapping:

WithTable("Addresses", join =>

                           {

                               join.Map(prop => prop.StreetAddress1, "StreetAddress1");

                            join.Map(prop => prop.StreetAddress2, "StreetAddress2");

                            join.Map(prop => prop.City, "City");

                            join.Map(prop => prop.State, "State");

                            join.Map(prop => prop.ZipCode, "ZipCode");

                               join.WithKeyColumn("PersonId");

                            join.SetAttribute("optional", "true");

                           });

Submit this story to DotNetKicks

FluentNHibernate Mappings: One-To-One

Recently Oren (Ayende) had a serious of posts on NHibernate mappings and the various options you can configure using Xml mappings. This series of posts takes those examples and shows how you can use FluentNHibernate to configure the same mappings.

This is a companion post for Oren’s post on the <one-to-one> mapping in NHibernate, here. I recommend reading his post before venturing forward.

In FluentNHibernate one-to-one mappings are achieved by using the HasOne mapping method on the parent and the References method on the child. Below is the mapping for the Person entity that has a one-to-one relationship with an Employee entity:

            HasOne(prop => prop.Employee)
                .PropertyRef(prop => prop.Person);

You can also specify the actual property that HasOne uses to specify the foreign key relationship using the PropertyRef method. The above statement basically creates a mapping instruction that reads “Person has a one-to-one relationship with Employee on the Person property of the Employee entity”.

Similarly, the Employee mappings use the References mapping method to specify the bi-directional part of the relationship. Here’s the full class mapping for Employee:

    public class EmployeeMap : ClassMap<Employee>
    {
        public EmployeeMap()
        {
            WithTable("Employees");
            Id(prop => prop.Id).GeneratedBy.Native();
            Map(prop => prop.Role);
 
            References(prop => prop.Person)
                .ColumnName("PersonId")
                .FetchType.Select()
                .LazyLoad()
                .Unique();
        }

The References mapping method in EmployeeMap generates a many-to-one mapping to the Person entity. You must add the Unique mapping modifier to instruct that the many-to-one mapping maps to a unique Person instance making it effectively a one-to-one mapping. You’ll also notice that I’ve set the FetchType to Select, this is done so that associated Person instances are lazy loaded when needed.

Submit this story to DotNetKicks

Wednesday, May 13, 2009

FluentNHibernate Mappings: HasMany

Recently Oren (Ayende) had a serious of posts on NHibernate mappings and the various options you can configure using Xml mappings. This series of posts takes those examples and shows how you can use FluentNHibernate to configure the same mappings.

This is a companion post for Oren’s post on the <set> mapping in NHibernate, here. I recommend reading his post before venturing forward.

A <set> element in NHibernate’s mapping refers to a one-to many mapping. This can be represented simply in FluentNHibernate using the HasMany mapping method:

 HasMany(prop => prop.Comments);

The HasMany statement simply specifies that the entity has a one-to-many relationship with the Comment entity as represented by the Comments property.

Specifying the foreign key name.

If you need to specify the foreign key column on the relationship you can use the KeyColumnNames property and use the Add method to specify the column name:

HasMany(prop => prop.Comments)
                .KeyColumnNames.Add("CreatedBy");

The above code snippet shows that the foreign key column on the Comments relationship is named “CreatedBy”.

Fetching strategy for relationships:

By default the fetching strategy used by fluent-nhibernate for associations is not lazy loaded (for auto mapping the convention is to set lazy as true). You can override this behavior using the Lazy method

HasMany(prop => prop.Comments)
                .KeyColumnNames.Add("CreatedBy")
                .LazyLoad();

To specify that the collection should be loaded using an outer-join, use the FetchType property on the mapping. This mapping can be either; Select or Join. The first one is the default setting which uses a sparate Select statement to get the associated entities, whereas Join uses an outer join statement to get the associated entities.

HasMany(prop => prop.Comments)
                .KeyColumnNames.Add("CreatedBy")
                .LazyLoad()
                .FetchType.Join();

Note that when you specify FetchType as Join, even if you specify LazyLoad NHibernate will still pre-fetch the entities using a left outer join.

Defining an inverse relationship:

Inverse is specified by simply setting the association as Inverse()

HasMany(prop => prop.Comments)
                .KeyColumnNames.Add("CreatedBy")
                .LazyLoad()
                .FetchType.Join()
                .Inverse();

Submit this story to DotNetKicks

Tuesday, May 12, 2009

FluentNHibernate Mappings: Component

[Edit: Reformatted code snippets and removed unnecessary line breaks]

Recently Oren (Ayende) had a serious of posts on NHibernate mappings and the various options you can configure using Xml mappings. This series of posts takes those examples and shows how you can use FluentNHibernate to configure the same mappings.

This is a companion post for Oren’s post on <component> mappings in NHibernate, here. I recommend reading his post before venturing forward.

In this post I’ll show how you use FluentNHibernate instead of using NHibernate’s xml mapping files.

Based on Oren’s original post on <component> mapping, here is the full mapping file:

<class name="Person"
table="People">

<id name="Id">
<generator class="identity"/>
</id>
<property name="Name" />
<component name="Address">
<property name="Line1"/>
<property name="Line2"/>
<property name="City"/>
<property name="Country"/>
<property name="ZipCode"/>
</component>
</class>

Below are the mappings in FluentNHibernate:

Component(prop => prop.Address, mapping =>

{

     mapping.Map(prop => prop.StreetAddress1);

     mapping.Map(prop => prop.StreetAddress2);

     mapping.Map(prop => prop.City);

     mapping.Map(prop => prop.State);

     mapping.Map(prop => prop.ZipCode);

});

Basically the Component method allows you to specify which property in your entity is treated as a Component and then allow to provide mappings for the properties of the component itself.

Submit this story to DotNetKicks

Fluent NHibernate Mappings: Property

Recently Oren (Ayende) had a serious of posts on NHibernate mappings and the various options you can configure using Xml mappings. This series of posts takes those examples and shows how you can use FluentNHibernate to configure the same mappings.

This is a companion post for Oren’s post on property mappings in NHibernate, here. I recommend reading his post before venturing forward.

In this post I’ll show how you use FluentNHibernate instead of using NHibernate’s xml mapping files.

Based on Oren’s original post on <property> mapping, here is the full mapping file:

<class name="Blog"
table="Blogs">

<id name="Id">
<generator class="identity"/>
</id>
<version name="Version"/>
<property name="Title" update="false"/>
<property name="Subtitle" optimistic-lock="insert"//>
<property name="AllowsComments" insert="false"/>
<property name="CreatedAt" />
<property name="CountOfPosts"
formula="(select count(*) from Posts where Posts.Id = Id)"/>
</class>

Below is the matching FluentNHibernate mapping:

public class PersonMap : ClassMap<Person>

{

    public PersonMap()

    {

        WithTable("Persons");

        Id(prop => prop.Id)

            .GeneratedBy.Identity();

 

        Version(prop => prop.Version);

        Map(prop => prop.FirstName);

        Map(prop => prop.LastName).SetAttribute("optimistic-lock", "false");

        Map(prop => prop.DateOfBirth);

        Map(prop => prop.Active).SetAttribute("generated", "insert");

        Map(prop => prop.CountOfComments)

            .FormulaIs("(Select Count('') from Comments Where Comments.CreatedBy = Id)");

    }

}

A couple of notes:

  1. You can use the Version() method to specify a version property in your class.
  2. There is no inbuilt way to specify optimistic-lock attribute in FluentNHibernate right now, at least I couldn’t find one. But you can use the SetAttribute method to inject in the attribute value.
  3. Similarly, there is no inbuilt way to specify that a column value is generated by the database, but just like in the case of optimistic-lock, you can use the SetAttribute method to inject the attribute.
  4. FormulaIs can be used to specify a custom formula for a property.

Submit this story to DotNetKicks