سؤال

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?

هل كانت مفيدة؟

المحلول

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>();
    }
    
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top