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.