The code for one-to-many relationships in Entity Framework comes first.

entity-framework one-to-many relationship

Question

I am having my first steps in EF 4.1. Because I was using NHibenate, the code first approach seems to me as the best one. I have problem with good mapping of one-to-many (or many-to-one) realtionship. Let's say I have 2 entities:

class ClientModel
{
    int ClientID;
    string Name;
    virtual IList<OrderModel> Orders;
}

class OrderModel
{
    int OrderID;
    string Details;
    virtual ClienModel Client;
}

When I leave it like that, there is an error while generating database - keys in tables are missing. I figured out I can fix it by changing names of the keys to ID (but it's not OK with my naming convention) or by adding [Key] annotation. Even if I add this annotation, still the names of tables are wrong - just like classes names but with 's'. So I tried to use fluent API - I made mappings. But if I set mappings just like here:

class ClientMapping
{
    ClientMapping()
    {
        this.HasKey(e => e.ClientID).Property(e => e.ID).HasColumnName("ClientID");
        this.Property(e => e.Name).HasColumnName("Name");
        this.HasMany(e => e.Orders).WithOptional().Map(p => p.MapKey("OrderID")).WillCascadeOnDelete();
        this.ToTable("Clients");
    }
}

class OrderMapping
{
    OrderMapping()
    {
        this.HasKey(e => e.OrderID).Property(e => e.OrderID).HasColumnName("OrderID");
        this.Property(e => e.Details).HasColumnName("Details");
        this.HasRequired(e => e.Client).WithMany().Map(p=>p.MapKey("Client")).WillCascadeOnDelete(false);
        this.ToTable("Orders");
    }
}

the relation betweene tables in database is doubled. What is the proper way to do one-to-many relationship using code-first approach? Am I thinking in a good direction or is it a wrong approach?

EDIT

OK, I have done it in the way @Eranga showed, but there is still a problem. When I'm getting Client from database, its Orders property is null (but in database it has some Orders with Order.ClientID == Client.ClientID).

1
3
9/23/2011 7:13:53 AM

Accepted Answer

You need to map both properties participating in the relationship. You need to add ClientID column to Orders table.

class ClientMapping
{
    ClientMapping()
    {
        this.HasKey(e => e.ClientID).Property(e => e.ID).HasColumnName("ClientID");
        this.Property(e => e.Name).HasColumnName("Name");

        this.HasMany(e => e.Orders).WithRequired(o => o.Client)
           .Map(p => p.MapKey("ClientID")).WillCascadeOnDelete();

        this.ToTable("Clients");
    }
}

class OrderMapping
{
    OrderMapping()
    {
        this.HasKey(e => e.OrderID).Property(e => e.OrderID).HasColumnName("OrderID");
        this.Property(e => e.Details).HasColumnName("Details");
        this.ToTable("Orders");
    }
}

Configuring the relationship from one entity is sufficient.

6
9/21/2011 2:06:27 PM

Popular Answer

This may help (it helped me, when i couldn't figure out how this works):

If you would have the classes like this:

class ClientModel
{
    int ClientId;
    string Name;
}

class OrderModel
{
    int OrderId;
    string Details;
    int ClientId;
}

Then this would represent 2 tables in your database which "wouldn't" be connected with each other via a foreign key (they would be connected via the ClientId in the OrderModel) and you could get data like "GetAllOrdersWithSomeClientId" and "GetTheClientNameForSomeClientId" from the database. BUT problems would arise when you would delete a Client from the database. Because then there would still be some Orders which would contain a ClientId which doesn't exist in the Client table anymore and that would lead to anomalies in your database.

The virtual List<OrderModel> Orders; (in the ClientModel) and virtual ClienModel Client; (in the OrderModel) are needed to create the relation aka. the foreign key between the tables ClientModel and OrderModel.

There is one thing about which i'm still not sure about. Which is the int ClientId; in the OrderModel. I guess that it has to have the same name as the ClientId in the ClientModel so that the entity framework knows which 2 attributes the foreign key has to connect. Would be nice if someone could explain this in detail.

Also, put this into your DbContext constructor if something souldn't work:

this.Configuration.ProxyCreationEnabled = false;
this.Configuration.LazyLoadingEnabled = false;


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow