Mapping Relationships

Fluent Linq to Sql supports mapping one-to-many, many-to-one and one-to-one relationships. Note that in all these examples the use of EntitySet/EntityRef is optional, but they are needed if you want to take advantage of lazy loading.

One to Many Relationships

Imagine that in your database the Customer table has a one-to-many relationship with an Order table. In your object model this relationship can be modeled as:

public class Customer {
   public int Id { get; set; }
   
   private EntitySet<Order> orders = new EntitySet<Order>();
   
   public IList<Order> Orders { 
      get { return orders; }
      set { orders.Assign(value); } 
   }
}

public class Order {
   public int Id { get; set; }
   public int CustomerId { get; set; } 
   //Other properties
}

To map the one-to-many relationship you will need to add the following code to your CustomerMapping:

public class CustomerMapping : Mapping<Customer> {
   public CustomerMapping() {
      Identity(x => x.Id);
      HasMany(x => x.Orders).OtherKey(x => x.CustomerId);
   }
}

public class OrderMapping : Mapping<Order> {
    public OrderMapping() {
        Identity(x => x.Id);
        Map(x => x.CustomerId);
        //other property mappings
    }
}

The HasMany method call in the CustomerMapping specifies that the Customer object has a one-to-many relationship to the Order object using the Orders property. If is also necessary to specify the foreign key property on the Order class using the OtherKey method so that Linq to Sql knows how to perform the join.

One-to-many relationships

The other side of the Customer-Order relationship could be modeled like this:

public class Order {
   public int Id { get; set; }
   public int CustomerId { get; set; }

   private EntityRef<Customer> customer;

   public Customer Customer {
      get { return customer.Entity; }
      set { customer.Entity = value; } 
   }
}

...and the mapping would look like this:

public class OrderMapping : Mapping<Order> {
    public OrderMapping() {
        Identity(x => x.Id);
        Map(x => x.CustomerId);
        BelongsTo(x => x.Customer).ThisKey(x => x.CustomerId);
    }
}

Note that this time we use the BelongsTo method to specify that the Order is on the "many" side of the one-to-many. We still have to specify the foreign key property, but this time you use the ThisKey method.

Bidirectional Relationships

If your relationships are bidirectional (that is, you have mapped both the one-to-many and many-to-one side of the relationship) it is necessary that you keep both sides of the relationship synchronised. If you are using EntitySet objects for your collections then you can use the onAdded/onRemoved parameters to keep both sides of the relationship in sync:

public class Customer {
	private readonly EntitySet<Order> orders;

	public Customer() {
		orders = new EntitySet<Order>(	order => order.Customer = this, 
								order => order.Customer = null);
	}
	//other properties...
}

If you are not using EntitySets then you will need to ensure that whenever you add an Order to the Customer's Order collection that the Customer property has been correctly set.

One-to-one relationships

If you have a true one-to-one relationship (rare) then you can use the HasOne method to map this.

Last edited Sep 6, 2009 at 1:55 PM by JeremyS, version 2

Comments

No comments yet.