Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent NHibernate enforce Not Nullable on Foreign Key Reference

Just getting my feet wet with some Fluent NHibernate AutoMap conventions, and ran into something I couldn't figure out. I assume I'm just not looking in the right place... Basically trying to enforce NOT-NULL on the "many" side of the one to many relationship. It seems, using the automapping, it always makes the parent property Id nullable in the database.

I did some searching on StackOverFlow and found similar questions, but nothing relating to AutoMapping and Conventions though (unless I missed it).

Quick example...

public class Group    // One Group
{
    public Group() { this.Jobs = new List<Job>(); }
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<Job> Jobs { get; protected set; }
}

public class Job    // Has many Jobs
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }

    // Trying to make this field not-nullable in the database.
    public virtual Group Group { get; set; }
}

I thought I'd be able to just create a convention like...

public class OneToManyConvention : IHasOneConvention
{
    public void Apply(IOneToOneInstance instance)
    {
        // Nullable() isn't a valid method...
        instance.Not.Nullable();   
    }
}

But it seems IOneToOnInstance doesn't have a Nullable() method. I can do this if I create a Map file for Job, but trying to avoid any Map files and stick with auto-mapping.

I came across this link on the Fluent group list describing something similar.

Which describes something like this...

public class NotNullPropertyConvention : IPropertyConvention
{
    public bool Accept(IProperty target)
    {
            return true;
    }
    public void Apply(IProperty target)
    {
            target.Not.Nullable();
    }
}

But that raises the questions of... 1) How would I determine IProperty to be a Job (or any child property that is a link back to the parent)

2) It made a mention on that page that using this would override my manual overrides, eg. if a very specific property link needed to be NULL. Which would be an issue (if it's still an issue, but can't test without figuring out #1 first)

Any ideas on this? Am I just missing something?



Update 1

Still no go. Even the following still doesn't enforce Not-Nullable in the database schema...

public class FluentConvention : IPropertyConvention
{
    public void Apply(IPropertyInstance instance)
    {
        instance.Not.Nullable();
    }
}

It does for all of the other fields though...
/shrug

Any ideas?



Update 2

While this isn't the answer I was looking for, I did find a work around... I was using NHibernate Validator assembly, and within that assembly there is a [NotNull] attribute. If I decorated my class with the Validator attribute, and associated the ValidationEngine to NHibernate before the schema creation, it would tag the FK database column as Not-Nullable.

public class Job    // Has many Jobs
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }

    [NHibernate.Validator.Constraints.NotNull]
    public virtual Group Group { get; set; }
}

If anyone needs the full code for the NHibernate + ValidationEngine initialization, just let me know. Still looking for a way to do it using the pure mapping convention route though if anyone has any info...

Thanks!

like image 301
Steve Foster Avatar asked Nov 24 '09 17:11

Steve Foster


1 Answers

You can override the auto-mapped properties as part of your AutoMap in Fluenttly.Configure().

So you can do this:

.Override<Job>(map => map.References(x => x.Group).Not.Nullable())

It's not exactly convenient if you have a lot of classes that need this though.

Edit: You can also specify the override in a class that implements IAutoMappingOverride like so:

    public class JobMappingOverride : IAutoMappingOverride<Job>
    {
            public void Override(AutoMapping<Job> mapping)
            {
                    mapping.References(x => x.Group).Not.Nullable();
            }
    }

and include it like so:

    .UseOverridesFromAssemblyOf<JobMappingOverride>()

This would keep your fluent configuration a little cleaner.

like image 113
Sean Gough Avatar answered Sep 22 '22 16:09

Sean Gough