3
votes

I'm an NHibernate and fluent-nhibernate newbie. And I've got some problem with unique constraint and nhibernate mapping.

I've got the following part of domain model.

public class Batch
{
    public virtual int Id {get; set;}
    public virtual string Name {get; set;}
    public virtual IList<BatchParameter> BatchParameters {get; set;}
}
public class BatchParameter
{
    public virtual int Id {get; set;}
    public virtual string Name {get; set;}
    public virtual Batch Batch {get; set;}
}

I'm trying to use fluent-nhibernate to map it on the db (SQLServer) using automapping. I want to be set up my db in order to have :

  • Primary Keys on the "Id"s properties

  • a Foreign Key on the BatchParamets table

  • a Unique Constraint on the Batch table on column Name

  • a Unique Constraint on the BatchParameters table on columns Name and Batch_Id

So I've written down this code:

public class BatchMapping : IAutoMappingOverride<Batch>
{
    public void Override(FluentNHibernate.Automapping.AutoMapping<Batch> mapping)
    {
        mapping.Id( b => b.Id);
        mapping.HasMany<BatchParameter>(p => p.BatchParameters).Cascade.All().Inverse();
    }
}

public class BatchParameterMapping : IAutoMappingOverride<BatchParameter>
{
    public void Override(FluentNHibernate.Automapping.AutoMapping<BatchParameter> mapping)
    {
        mapping.Id( b => b.Id);
        mapping.Map(b => b.Name).Unique();
        //mapping.Map(p => p.Name).UniqueKey("Batch_Parameter");
        //mapping.Map(p => p.Batch.Id).UniqueKey("Batch_Parameter");
    }
}

No problems for the primary keys, the foreign key and the first Unique Constraint. A little bit of headache for the Unique Constraint.

Can someone show me the straight way???

Thanks!

2

2 Answers

2
votes

First, it looks like you have a copy-and-paste error: ...Map(b => b.Name)... should go in BatchMapping, not BatchParameterMapping.

public class BatchMapping : IAutoMappingOverride<Batch>
{
    public void Override(AutoMapping<Batch> mapping)
    {
        mapping.Map(b => b.Name).Unique();
    }
}

Next, BatchParameter.Batch is a many-to-one relationship from BatchParameter to Batch, so it should be mapped with References(...) instead of Map(...). You use References for foreign keys to another entity and use Map for simple properties.

public class BatchParameterMapping : IAutoMappingOverride<BatchParameter>
{
    public void Override(AutoMapping<BatchParameter> mapping)
    {
        mapping.Map(p => p.Name).UniqueKey("Batch_Parameter");
        mapping.References(p => p.Batch).UniqueKey("Batch_Parameter");
    }
}

Finally, you should remove the unnecessary mappings for the Id properties and Batch.BatchParameters. Fluent NHibernate's auto-mapping will map them as desired by default. In your Override methods you only need to specify the properties where you want to do something differently than the auto-mapping default, such as specifying unique keys.

0
votes

If Id and Name are primary keys in your BatchParameter table you would need a composite id. Also if you want to have a reference back to Batch from your BatchParameter class you will need to use Reference. The following should be close to what you need:

public class BatchParameterMapping : IAutoMappingOverride<BatchParameter>
{
    public void Override(FluentNHibernate.Automapping.AutoMapping<BatchParameter> mapping)
    {
        mapping.CompositeId()
            .KeyProperty(x => x.Id)
            .KeyProperty(x => x.Name);

        mapping.References(x => x.Batch);
    }
}