Try fast search NHibernate

08 October 2010

Castle Windsor InstantiateAndForgetIt Lifestyle

Directly to the point.

The case

public interface IMySingleton : IDisposable
{
}

public class MySingleton: IMySingleton
{
    public void Dispose()
    {
    }
}

public interface IMyTransient
{
}

public class MyTransient : IMyTransient
{
    private readonly IMySingleton singleton;

    public MyTransient(IMySingleton singleton)
    {
        this.singleton = singleton;
    }
}
As you can see it is pretty common: I have a class MyTransient with a dependency from a singleton. The singleton is disposable.
The transient is from the point of view of its usage, that mean that its lifecycle is managed by an “external context” and, as is, it does not need a special “destructor”. The “external context” may hold the instance somewhere or may use it only in the context of a method and can quite leave the destruction to the garbage collector. If/when MyTransient implements IDisposable the “external context” should dispose the instance. You can see this behavior in various places for example in the DefaultControllerFactory of Asp.NET MVC or in the IInstanceProvider of WCF (both has a ReleaseInstance cheking for IDisposable); personally I have this situation in other places.
If I do something like this
var myInstance = new MyTransient(container.Resolve<IMySingleton>());
The garbage collector will have zero problems to destroy myInstance and I’ll have zero memory leaks… that is clear, no ?

The test using Windsor with Transient Lifestyle

public class TransientLeak
{
    private WindsorContainer GetContainerConfiguredWindsorContainer()
    {
        var container = new WindsorContainer();
        container.Register(Component.For<IMySingleton>().ImplementedBy<MySingleton>());
        container.Register(Component.For<IMyTransient>().ImplementedBy<MyTransient>().LifeStyle.Transient);
        return container;
    }

    [Test]
    public void WhenTransientRequiredThenReturnDifferentInstances()
    {
        using (WindsorContainer container = GetContainerConfiguredWindsorContainer())
        {
            var t0 = container.Resolve<IMyTransient>();
            var t1 = container.Resolve<IMyTransient>();

            t0.Should().Not.Be.SameInstanceAs(t1);
        }
    }

    [Test]
    public void WhenTransientRequiredThenContainerShouldntHaveInstancesOfMyTransient()
    {
        using (WindsorContainer container = GetContainerConfiguredWindsorContainer())
        {
            var t0 = container.Resolve<IMyTransient>();
            var t1 = container.Resolve<IMyTransient>();

            container.Kernel.ReleasePolicy.Satisfy(rp=> !rp.HasTrack(t0));
            container.Kernel.ReleasePolicy.Satisfy(rp => !rp.HasTrack(t1));
        }
    }     
}
Well… the first test pass, that means that each time I asking for a IMyTransient I’ll have a new instance of the concrete implementation injected with the same instance of IMySingleton (as expected).

Now take care : The second test fails. That means that the container is holding two instances of MyTransient class; let me show you where:
TransientLeak
Perhaps there is a good explication for this behavior but I must admit that I can’t understand why all instances of MyTransient should have its lifecycle stuck to the lifecycle of MySingleton only because MySingleton is disposable… bah?!? by the way that is not a matter because Castle.Windsor give us the ability to define the behavior we need.

The solution

First of all I need my custom lifestyle manager:
[Serializable]
public class InstantiateAndForgetIt : ILifestyleManager
{
    private IComponentActivator componentActivator;

    public void Init(IComponentActivator componentActivator, IKernel kernel, ComponentModel model)
    {
        this.componentActivator = componentActivator;
    }

    public object Resolve(CreationContext context)
    {
        return componentActivator.Create(context);
    }

    public bool Release(object instance)
    {
        return true;
    }

    public void Dispose()
    {
     
    }
}

Pretty simple but not enough. Then I need an implementation of IReleasePolicy and I can simply inherit from the default and override a method:
[Serializable]
public class LifecycledComponentsReleasePolicy : Castle.MicroKernel.Releasers.LifecycledComponentsReleasePolicy
{
    private readonly Type instantiateAndForgetItType = typeof (InstantiateAndForgetIt);

    public override void Track(object instance, Burden burden)
    {
        if (instantiateAndForgetItType.Equals(burden.Model.CustomLifestyle))
        {
            return;
        }
        base.Track(instance,burden);
    }
}

The last step is the modification of the container’s configuration:
private WindsorContainer GetContainerConfiguredWindsorContainer()
{
    var container = new WindsorContainer();
    container.Kernel.ReleasePolicy = new LifecycledComponentsReleasePolicy();
    container.Register(Component.For<IMySingleton>().ImplementedBy<MySingleton>());
    container.Register(Component.For<IMyTransient>().ImplementedBy<MyTransient>().LifeStyle.Custom<InstantiateAndForgetIt>());
    return container;
}


Work done!! and bye bye “memory leaks”.


Update: request to have InstantiateAndForgetIt Lifestyle natively supported issue IOC-225 (vote for it)

05 October 2010

NHibernate 3.0 Cookbook.

This week Packt published the NHibernate 3.0 Cookbook. Packt are offering all members of the NHibernate community 20% off the book.
The book helps users to get solutions to common NHibernate problems to develop high-quality performance-critical data access applications.
The book, which is 328 pages long, contains quick-paced self-explanatory recipes organized in progressive skill levels and functional areas.
Overview of NHibernate 3.0 Cookbook
  • Master the full range of NHibernate features
  • Reduce hours of application development time and get better application architecture and performance
  • Create, maintain, and update your database structure automatically with the help of NHibernate
  • Written and tested for NHibernate 3.0 with input from the development team distilled in to easily accessible concepts and examples
  • Part of Packt's Cookbook series: each recipe is a carefully organized sequence of instructions to complete the task as efficiently as possible
Is this book for you?
This book is written for NHibernate users at all levels of experience. Examples are written in C# and XML. Some basic knowledge of SQL is assumed.
To get your exclusive 20% discount when you buy through PacktPub.com, just enter the discount code NHIBCBK20 (case sensitive), to the shopping cart.
Click here to read more about the NHibernate 3.0 Cookbook.

06 September 2010

ConfORM: Usage Examples

I have promised myself to no post often about ConfORM, instead I have started a new project, available with ConfORM’s sources, where I’ll show some usage examples with some explication.

So far there are few examples created under users requests. If you want see the code without download, it is available here.

Taking the opportunity of this post I would show you another success story:
It is about an “Inventory management and stock control” system composed by 65 entities/components where the persistence is managed using NHibernate 2.1.2. Because ConfORM uses a NHibernate 3 specific feature they can’t use ConfORM directly in the application, instead they are using ConfORM to generate XML mappings (soon, probably, they will use it directly with NHibernate 3). They can trust in ConfORM because they have, so far, 83 persistence integration-tests testing CRUD and expected cascades operations.

I can’t show you the domain-model but I can show you the whole mapping:

IEnumerable<Type> domainEntities = typeof (BaseEntity)
    .Assembly.GetTypes()
    .Where(t => typeof (BaseEntity).IsAssignableFrom(t) && !t.IsGenericType)
    .ToList();

var tablePerClassHierarchy = new[] {typeof (Movement), typeof (MovementDetail)};
IEnumerable<Type> tablePerClassEntities = typeof (BaseEntity)
    .Assembly.GetTypes()
    .Where(t => typeof (BaseEntity) == t.BaseType && !tablePerClassHierarchy.Contains(t))
    .ToList();

var orm = new ObjectRelationalMapper();

orm.TablePerClass(tablePerClassEntities);
orm.TablePerClassHierarchy(tablePerClassHierarchy);

orm.Exclude(typeof (Movement<>));
orm.Exclude(typeof (MovementDetail<>));

orm.ManyToMany<Product, Tag>();

var patternsAppliers =
    (new SafePropertyAccessorPack())
        .Merge(new OneToOneRelationPack(orm))
        .Merge(new BidirectionalManyToManyRelationPack(orm))
        .Merge(new BidirectionalOneToManyRelationPack(orm))
        .Merge(new DiscriminatorValueAsClassNamePack(orm))
        .Merge(new CoolTablesAndColumnsNamingPack(orm))
        .Merge(new TablePerClassPack())
        .Merge(new DatePropertyByNameApplier())
        .Merge(new MsSQL2008DateTimeApplier());

var mapper = new Mapper(orm, patternsAppliers);

mapper.Customize<Product>(
    cm =>
        {
            cm.Property(product => product.Code, pm =>
                                                     {
                                                         pm.NotNullable(true);
                                                         pm.Unique(true);
                                                     });
            cm.Collection(product => product.Tags, tagsm => tagsm.Cascade(Cascade.Persist));
        });

mapper.Customize<Role>(
    cm => cm.Collection(role => role.Functionalities, com => com.Cascade(Cascade.Persist)));

mapper.Customize<User>(cm => cm.Property(user => user.Nick, n => n.Unique(true)));

In this mapping you can see how compose ConfOrm.Shop.Packs and how map a whole domain in few lines ;-)

Are you ConfORM ?
They are!!!