Search code examples
nhibernatefluent-nhibernateautomapping

Defining unique column in Fluent NHibernate Automap Override


I'm trying to specify a unique column for an entity, using the Fluent NHibernate Automapper Override. For my test class of CodeType, I'd like to make the Type property unique. The goal would be for a "new CodeType()" being created with the same type field as a currently saved CodeType to be overlaid on top of the current entity.

I have the following CodeType class:

public class CodeType : SecurableEntity
{

    public virtual string Type { get; set; }
    public virtual string Description { get; set; }

    /// <summary>
    /// This is a placeholder constructor for NHibernate.
    /// A no-argument constructor must be available for NHibernate to create the object.
    /// </summary>
    public CodeType() { }


}

I have the following CodeTypeMap Class:

public class CodeTypeMap : IAutoMappingOverride<CodeType>
{
    public void Override(AutoMapping<CodeType> mapping)
    {
        //Doesn't work. Need a way to specify a column as unique.
        mapping.Map(m => m.Type).Unique();
    }
}

The override is applied to the AutoMap, through the following:

    public AutoPersistenceModel Generate()
    {
        var mappings = AutoMap.AssemblyOf<User>(new AutomappingConfiguration());
        mappings.IgnoreBase<Entity>();
        mappings.IgnoreBase<SecurableEntity>();
        mappings.IgnoreBase(typeof(EntityWithTypedId<>));
        mappings.Conventions.Setup(GetConventions());
        mappings.UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();
        mappings.UseOverridesFromAssemblyOf<UserMap>();
        mappings.UseOverridesFromAssemblyOf<CodeMap>();
        mappings.UseOverridesFromAssemblyOf<CodeTypeMap>();

        return mappings;
    }

I'd like the following code to update any existing record with "type" equal to "existingType".

SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
CodeType ct = new CodeType();
ct.type = "existingType";
ct = ctr.SaveOrUpdate(ct);

How can I make NHibernate key off of the type field as unique?

Is this possible?


Solution

  • short answer, what you want is something you have to handle in code because there are so many possibilities. Everytime you create a new CodeType you have to check the db if there is already one

    SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
    CodeType ct = ctr.GetByType("existingType");
    if (ct == null)
    {
        ct = new CodeType { type = "existingType" };
    }
    ctr.SaveOrUpdate(ct);
    

    or

    SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
    CodeType ct = ctr.GetByType("existingType");
    if (ct != null)
    {
        ctr.Detach(ct);
        ctr.Merge(new CodeType{ type = "existingType" });
    }
    

    or

    SecurableEntityRepository<CodeType> ctr = new SecurableEntityRepository<CodeType>();
    int ctId = ctr.GetIdByType("existingType");
    if (ct != 0)
    {
        ctr.Merge(new CodeType{ Id = ctId, type = "existingType" });
    }
    

    and there are some things which can be written differently

    • public CodeType() { } can be removed or made protected CodeType() { } if not needed for your domain

    • public AutoPersistenceModel Generate()
      {
          return AutoMap.AssemblyOf<User>(new AutomappingConfiguration())
              .IgnoreBase<Entity>()
              .IgnoreBase<SecurableEntity>()
              .IgnoreBase(typeof(EntityWithTypedId<>))
              .Conventions.Setup(GetConventions())
              .UseOverridesFromAssemblyOf<AutoPersistenceModelGenerator>();
      }