41

I am new to Fluent NHibernate and have been unable to figure out how to map composite keys.

How can I do this? What approach do I need to take?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
pang
  • 3,964
  • 8
  • 36
  • 42
  • Can find more detailed example here: https://web.archive.org/web/20111021204316/http://devlicio.us/blogs/derik_whittaker/archive/2009/01/16/using-fluentnhibernate-to-map-composite-keys-for-a-table.aspx – Derik Whittaker Jan 28 '09 at 19:44

4 Answers4

53

There's a CompositeId method.

public class EntityMap : ClassMap<Entity>
{
  public EntityMap()
  {
      CompositeId()
      .KeyProperty(x => x.Something)
      .KeyReference(x => x.SomethingElse);
  }
}
gdoron
  • 147,333
  • 58
  • 291
  • 367
James Gregory
  • 14,173
  • 2
  • 42
  • 60
  • 18
    Note that in new versions of NHibernate UseCompositeId is replaced with CompositeId, and WithKeyProperty is just KeyProperty – Rob Walker Oct 28 '10 at 17:20
  • 2
    @Rob Walker : Also WithReferenceProperty has become KeyReference – Whimsical Feb 18 '11 at 07:48
  • 6
    What's the difference in KeyProperty and KeyReference in this case? – Johnny_D Apr 28 '12 at 11:43
  • 6
    The examples i'm seeing suggest that KeyProperty would be the "ID" and KeyReference would be the Entity. So use KeyProperty for "CustomerID", use KeyReference for "Customer" instance – JDPeckham Oct 18 '12 at 18:08
5

Another thing to note is that you must override the Equals and GetHashCode methods for an entity using a CompositeId. Given the accepted answers mapping file, your entity would look like this.

public class Entity
{
   public virtual int Something {get; set;}
   public virtual AnotherEntity SomethingElse {get; set;}


   public override bool Equals(object obj)
    {
        var other = obj as Entity;

        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other.SomethingElse == SomethingElse && other.Something == Something;
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return (SomethingElse.GetHashCode()*397) ^ Something;
        }
    }

}
Kyle Mountney
  • 51
  • 1
  • 1
5

if this is your first class

public class EntityMap : ClassMap<Entity>
{
  public EntityMap()
  {
    UseCompositeId()
      .WithKeyProperty(x => x.Something)
      .WithReferenceProperty(x => x.SomethingElse);
  }
}

here is the second with a reference on Entity

public class SecondEntityMap : ClassMap<SecondEntity>
    {
      public SecondEntityMap()
      {
        Id(x => x.Id);

        ....

        References<Entity>(x => x.EntityProperty)
          .WithColumns("Something", "SomethingElse")
          .LazyLoad()
          .Cascade.None()
          .NotFound.Ignore()
          .FetchType.Join();

      }
    }
1

There may be a need for entities with composite identifiers, entities that map to tables which have composite primary keys, composed of many columns. The columns that make up this primary key are usually foreign keys to another tables.

public class UserMap : ClassMap<User>
{      
   public UserMap()
   {
        Table("User");

        Id(x => x.Id).Column("ID");

        CompositeId()
          .KeyProperty(x => x.Id, "ID")
          .KeyReference(x => x.User, "USER_ID");

        Map(x => x.Name).Column("NAME");               

        References(x => x.Company).Column("COMPANY_ID").ForeignKey("ID");
    }
}

For more reference : http://www.codeproject.com/Tips/419780/NHibernate-mappings-for-Composite-Keys-with-associ

Matthew Walton
  • 9,809
  • 3
  • 27
  • 36
Deepak
  • 420
  • 5
  • 21
  • 1
    "The columns that make up this primary key are usually foreign keys to another tables." No, not usually. If anything, they help identify an entity uniquely where one column fails to do so on its own. – tinonetic Oct 20 '15 at 08:35