0

I have to access a legacy database in which I'm faced with the following: A column 'unit_name' is defined as primary key and is a string, and another column 'id' is defined as a classic int identifier.

My question is - how do I map this correct in Fluent NHibernate?

Currently my mapping looks like this, but I can't find any proper documentation for my scenario, so I'm not sure if it is correct.

    public InputMap()
    {
        Table("input");
        Map(x => x.unit_name).Not.Nullable().Unique();
        //other mappings ...
        Id(x => x.id).Column("id").Not.Nullable();
        //Maybe use this instead? NaturalId().Property(x => x.unit_name);            
    }

Full context:

In my hunt for documentation I've created an id class that implements Equals and GetHashCode, but that might be overkill after all.

[Serializable]
public class GenericEntityId : EntityId, IEquatable<GenericEntityId>
{
    public GenericEntityId(string idString)
    {
        IdString = idString;
    }

    public string IdString { get; set; }

    private Guid _internalId { get; set; }

    protected GenericInoEntityId()
    {
        _internalId = Guid.NewGuid();
    }

    public virtual bool Equals(GenericEntityId obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (GetType() != obj.GetType()) return false;
        if (!string.IsNullOrEmpty(IdString) )
            return obj.IdString == IdString;
        return false;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (GetType() != obj.GetType()) return false;
        return Equals((GenericEntityId)obj);
    }

    public override int GetHashCode()
    {
        if (!string.IsNullOrEmpty(IdString))
        {
            return (IdString.GetHashCode() * 397) ^ GetType().GetHashCode();
        }
        else
        {
            return (_internalId.GetHashCode() * 397) ^ GetType().GetHashCode();
        }
    }

    public static bool operator ==(GenericEntityId left, GenericEntityId right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(GenericEntityId left, GenericEntityId right)
    {
        return !Equals(left, right);
    }
}

and EntityId is just an abstract class:

public abstract class EntityId
{
    public abstract override int GetHashCode();
}

The reason for creating an abstract base is that I want to have a generic base I can use for all my repositories no matter if they have a string primary key or a composite key (or maybe the identifier)

[Serializable]
public abstract class EntityBase
{
    public abstract EntityId entityId { get; }

    protected EntityBase()
    {
    }
}

public class GenericRepository<TEntity> : SessionManagerBase, IEntityRepository<TEntity> where TEntity : EntityBase
{
    public TEntity GetById(EntityId id)
    {
        ISession currentSession = OpenSession;

        var returnObject = currentSession.Get<TEntity>(id);
        return returnObject;
    }
}
Thestrup
  • 85
  • 1
  • 9

1 Answers1

0

This is Nhibernate mapping-by-code, but fluent should be similar

domain object class

public class TestEntity
{
    public String unit_name { get; set; }
    public Int32 id { get; protected set; }
}

mapping class

public class TestEntityMap : ClassMapping<TestEntity>
{
    public TestEntityMap()
    {
        Id( x => x.unit_name, map =>
        {
            map.Column("user_name");
            map.Generator(Generators.Assigned);
        });

        Property(x => x.id, map =>
        {
            map.Generated(PropertyGeneration.Always);
            map.Unique(true);
            map.NotNullable(true);
        });
    }
}
Fran
  • 6,440
  • 1
  • 23
  • 35
  • Can you explain why the user_name column should be mapped as id and not the id column, which is the identifier? – Thestrup Aug 12 '14 at 11:13
  • Because, as you stated, that is the primary key of the table. – Fran Aug 12 '14 at 11:44
  • Why does one create a table with a primary key in one column and then uses another column as identifier? What is the benefit? And from your answer I assume that NHibernate Id = key and not identifier? – Thestrup Aug 13 '14 at 10:57
  • @Thestrup Yes, the "Id()" in NHibernate mappings is to tell NH about what to use as a primary key. The fact that another column is named "id" doesn't matter, and the "identifier" column property found in MS SQL is something mostly specific to MS SQL - it has no counterpart in relational database theory and is basically an MS SQL implementation detail that _may_ be used as primary key. – Oskar Berggren Aug 26 '14 at 19:25