Tags: , | Categories: C#, Fluent, NHibernate Posted by Admin on 11/21/2011 4:06 PM | Comments (1)

So, Country has a collection of Counties

public class Country
{
    private IList<County> counties = new List<County>();
    public virtual IList<County> Counties
    {
        get { return this.counties; }
        set { this.counties = value; }
    }
}

Therefore County has a reference to Country

public class County
{
    public virtual Country Country { get; set; }
}

I was trying to create a new County and then add it to the Counties collection of a Country instance

public static void Something()
{
    Country country = repository.Get<Country>(countryId);
    County county = new County(){ Name = "Berkshire" };
    country.Counties.Add(county);    //this executes
    repository.Save<Country>(country);    //this bails
}

The solution was to test the parent Country's County collection within the Country setter of the County class

public class County
{
    private Country country = null;
    public virtual Country Country
    {
        get { return this.country; }
        set
        {
            this.country = value;
            if (!this.country.Counties.Contains(this))
            {
                this.country.Counties.Add(this);
            }
        }
    }
}

Why? Well I don't really know, but it works. I guess that there is something going on within NHibernate and object tracking, but that is just a guess!

For a more fluent way of doing the same thing

public class County
{
    public virtual Country Country { get; protected set; }
    
    public virtual County WithCountry(Country country)
    {
        this.country = value;
        if (!this.country.Counties.Contains(this))
        {
            this.country.Counties.Add(this);
        }

        return this;
    }
}
Tags: , | Categories: C#, Fluent Posted by Admin on 9/21/2011 8:17 AM | Comments (0)

A while ago we wrote about fluent apis using interfaces, this is probably the 'text book' approach but since we're about real web development lets have a real world approach.

public class Country
{
    // backing field for the name property.
    private string name = string.Empty;

    // backing field for the code property;
    private string code = string.Empty;

    // accessor to the name backing field. The setter is private.
    public string Name
    {
        get { return this.name; }
        private set { this.name = value; }
    }

    // accessor to the code backing field. The setter is private.
    public string Code
    {
        get { return this.code; }
        private set { this.code = value; }
    }

    // chainable (fluent) method to set the name. Note this returns to instance of the entity whose property is being set.
    public Country WithName(string name)
    {
        this.Name = name;
        return this;
    }

    // chainable (fluent) method to set the code. Note this returns to instance of the entity whose property is being set.
    public Country WithCode(string code)
    {
        this.Code = code;
        return this;
    }
}

So if we were to use this class within an application we can now write code like

Country unitedKingdom = new Country().WithName("United Kingdom").WithCode("UK");
Tags: , , , , , , | Categories: ASP.Net, C#, Fluent, MVC, NHibernate, Ninject, NHibernate,Validator Posted by Admin on 9/14/2011 4:26 PM | Comments (1)

Eventually (after lots of google searches and putting together snippets from here, there and, everywhere) we now have Fluent NHibernate, NHibernate.Validator and Ninject all playing together.

First, we configure NHibernate using Fluent NHibernate passing the configuration to NHibernate.Validator so that it can configure the NHibernateSharedEngineProvider - this is important as Ninject will use the NHibernateSharedEngineProvider.

public static class Database
{
    private static ISessionFactory sessionFactory = null;

    public static ISessionFactory CreateSessionFactory()
    {
        var config = new AutoMappingConfiguration();
        ValidatorEngine validatorEngine = null;
        if (sessionFactory == null)
        {
                sessionFactory = Fluently
                .Configure()
                .Database(
                    MsSqlConfiguration
                    .MsSql2008
                    .ConnectionString(c => c.Server("").Database("").TrustedConnection()))
                .Mappings(
                    m => m.AutoMappings.Add(
                        AutoMap.AssemblyOf<EntityBase>(config)
                        .Override<EntityBase>(n => n.IgnoreProperty(c => c.ValidationErrors))
                        .Override<Country>(n => n.IgnoreProperty(c => c.DisplayName))
                        ))
                .ExposeConfiguration(c => { 
                    validatorEngine = ConfigureNHibernateValidator(c); 
                    BuildSchema(c); 
                })
                .BuildSessionFactory();
        }

        return sessionFactory;
    }

    public static ValidatorEngine ConfigureNHibernateValidator(Configuration nhibernateConfiguration)
    {
        NHibernate.Validator.Cfg.Environment.SharedEngineProvider = new NHibernateSharedEngineProvider();
        var validatorConfiguration = new NHibernate.Validator.Cfg.Loquacious.FluentConfiguration();
        validatorConfiguration
            .SetDefaultValidatorMode(ValidatorMode.UseAttribute)
            .Register(Assembly.Load("models").ValidationDefinitions())
            .IntegrateWithNHibernate
            .ApplyingDDLConstraints()
            .RegisteringListeners();
        var validatorEngine = NHibernate.Validator.Cfg.Environment.SharedEngineProvider.GetEngine();
        validatorEngine.Configure(validatorConfiguration);
        ValidatorInitializer.Initialize(nhibernateConfiguration, validatorEngine);
        return validatorEngine;
    }

    private static void BuildSchema(Configuration config)
    {
        new SchemaUpdate(config).Execute(false, true);
    }
}

Then we configure Ninject

private static void RegisterServices(IKernel kernel)
{
    kernel.Bind<IEntityManager>().To<EntityManager>().InRequestScope();
    kernel.Bind<ISessionFactory>().ToMethod(x => Database.CreateSessionFactory()).InSingletonScope();
    kernel.Bind<ISession>().ToMethod(x => kernel.Get<ISessionFactory>().OpenSession()).InRequestScope();
    kernel.Bind<ISharedEngineProvider>().ToMethod(x => NHibernate.Validator.Cfg.Environment.SharedEngineProvider).InSingletonScope();
}

Then we inject both ISession and ISharedEngineProvider into our EntityManager via the .ctor. We then check the Entity is valid before saving.

public class EntityManager : IEntityManager
{
    private ISession session = null;
    private ISharedEngineProvider validator = null;

    public EntityManager(ISession session, ISharedEngineProvider validator)
    {
        this.session = session;
        this.validator = validator;
    }

    public T Save<T>(T item) where T : EntityBase
    {
        item.ValidationErrors.Clear();
        ValidatorEngine ve = this.validator.GetEngine();
        if (!ve.IsValid(item))
        {
            foreach (var invalidValue in ve.Validate(item))
            {
                item.ValidationErrors.Add(new ValidationError() { PropertyName = invalidValue.PropertyName, Message = invalidValue.Message });
            }
        }
        else
        {   
            try
            {
                this.session.SaveOrUpdate(item);
                this.session.Flush();
            }
            catch (InvalidStateException ise)
            {
                item.ValidationErrors.Clear();
                foreach (var invalidValue in ise.GetInvalidValues())
                {
                    item.ValidationErrors.Add(new ValidationError() { PropertyName = invalidValue.PropertyName, Message = invalidValue.Message });
                }
            }
        }

        return item;
    }
}

Note that within EntityManager we use ISharedEngineProvider.GetEngine() to get our pre-configured Validator. The try { ... } catch { ... } around this.Session.SaveOrUpdate(item) isn't really required but better to be safe than sorry!

Tags: , , , , | Categories: ASP.Net, C#, Fluent, NHibernate Posted by Admin on 7/12/2011 10:05 AM | Comments (2)

When we wrote NHibernate logical (virtual, 'soft') deletion we showed how to implement virtual deletion of entities (i.e. set IsDeleted = true) by cross-cutting concerns in NHibernate. Since then we've discovered that this raises an issue; when you retrieve a list of entites from NHibernate it doesn't understand that it shouldn't get entites where IsDeleted = true. The initial solution was to add a constraint to our entities (since all our entities subclass BusinessBase we only needed to do this in one place) by adding a Fluent NHibernate Where clause.

public BusinessBaseMap()
{
    this.Where("IsDeleted = 0");
    this.Id(a => a.Id);
    this.Map(a => a.Created);
}

Note the string passed to .Where() is SQL.

The constraint did stop deleted entites from being returned but is completely ignored for related collections so you might not get deleted ProductCategories but the Products collection will include deleted Products; not ideal. This caused a little re-think until we realized that this isn't a bug in NHibernate; it isn't the duty of any ORM tool to implement business logic like this - it is the job of the business manager class(es). Needless to say, we left the constraint in place; if NHibernate is going to perform this function for us out-of-the-box we're going to us it!

So back to issue; how to exclude deleted entities from being return in collections? We decided to change our entities collections from 'auto' properties to use backing fields with accessors where the get accessor applies the constraint and NHibernate populates the backing field.

private IList<EmailAddress> emailAddresses = new List<EmailAddress>();
public virtual IList<EmailAddress> EmailAddresses 
{
    get
    {
        return this.emailAddresses.Where(a => !a.IsDeleted);
    }
}

We didn't even need to change our mappings; NHibernate defaults to using a backing field with the name of the property with a lower-case first letter.

Tags: , | Categories: C#, Fluent Posted by Admin on 5/15/2011 8:48 PM | Comments (0)

A 'usual' interface note this interface is primarily for properties.

public interface IBlogEntry : IBusinessBase
{
    string Title { get; set; }
    string HtmlContent { get; set; }
    string EmailAddress { get; set; }
}

An interface where the methods return the same interface. This allows for method chaining. Note this interface is primarily methods.

public interface IFluentBlogEntry : IBlogEntry
{
    IFluentBlogEntry WithTitle(string title);
    IFluentBlogEntry WithHtmlContent(string htmlContent);
    IFluentBlogEntry WithEmailAddress(string emailAddress);
}

A class implementing IFluentBlogEntry. Putting the implementaion of the different interfaces into seperate partial class files makes life somewhat easier.

public partial class BlogEntry : IFluentBlogEntry
{
    public virtual IFluentBlogEntry WithTitle(string title)
    {
        this.Title = title;
        return this;
    }

    public virtual IFluentBlogEntry WithHtmlContent(string htmlContent)
    {
        this.HtmlContent = htmlContent;
        return this;
    }

    public virtual IFluentBlogEntry WithEmailAddress(string emailAddress)
    {
        this.EmailAddress = emailAddress;
        return this;
    }

    public static IFluentBlogEntry Create()
    {
        return new BlogEntry();
    }
}

Finally a nice fluent codebase

BlogEntry entry = BlogEntry.Create()
    .WithTitle("A blog entry")
    .WithHtmlContent("<p>The best blog post in the world!</p>")
    .WithEmailAddress("user@example.com") as BlogEntry;