简体   繁体   中英

Entity Framework one to many relation code first

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).

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.

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;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM