Mapping EF Code First to an Existing Database - entity-framework

First let me apologize for the lengthy post. I figured giving more details would help you understand the situation.
I’m trying to develop the data layer of my application using EF 5 Code First and mapping everything to an existing database. I’m wanting to use DbContext, POCOs, fluent table mappings, etc., but our existing database (the tables) isn’t straight-forward. So, I’m having trouble with a few things. I’ll try to briefly describe the situation now, then ask a couple questions later.
Tables
AlarmDefinition
AlarmDefinitionID int (primary key) (is identity)
...
Alarm
AlarmID int (primary key) (is identity)
AlarmDefinitionID int (sort of a foreign key) (is nullable)
SampleTagID int (is nullable)
SampleTime DateTime (is nullable)
...
ReasonAction
Time DateTime (primary key)
TagID int (primary key)
ReasonActionID int (primary key)
ReasonActionDefinition
ReasonActionID int (primary key) (is identity)
...
So, one AlarmDefinition can have many Alarms. And, one ReasonActionDefinition can have many ReasonActions. There is an implicit relationship between Alarm and ReasonAction (i.e., one Alarm can have many ReasonActions). This is where I’m having the most troubles.
POCOs
AlarmDefinition
public class AlarmDefinition
{
public int AlarmDefinitionID { get; set; }
...
public virtual ICollection<Alarm> Alarms { get; set; }
}
Alarm
public class Alarm
{
public int AlarmID { get; set; }
public Nullable<int> SampleTagID { get; set; }
public Nullable<System.DateTime> SampleTime { get; set; }
...
public Nullable<int> AlarmDefinitionID { get; set; }
public virtual AlarmDefinition AlarmDefinition { get; set; }
// I don’t know if this is set up correctly
public virtual ICollection<ReasonAction> ReasonActions { get; set; }
}
ReasonAction
public class ReasonAction
{
public System.DateTime Time { get; set; }
public int TagID { get; set; }
public virtual Alarm Alarm { get; set; }
public int ReasonActionID { get; set; } // Primary key
public virtual ReasonActionDefinition ReasonActionDefinition { get; set; }
}
ReasonActionDefinition
public class ReasonActionDefinition
{
public int ReasonActionID { get; set; }
...
public virtual ICollection<ReasonAction> ReasonActions { get; set; }
}
DbContext
public class AppDbContext : DbContext
{
public DbSet<Alarm> Alarms { get; set; }
public DbSet<AlarmDefinition> AlarmDefinitions { get; set; }
public DbSet<ReasonAction> ReasonActions { get; set; }
public DbSet<ReasonActionDefinition> ReasonActionDefinitions { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new AlarmMap());
modelBuilder.Configurations.Add(new AlarmDefinitionMap());
modelBuilder.Configurations.Add(new ReasonActionMap());
modelBuilder.Configurations.Add(new ReasonActionDefinitionMap());
}
}
Fluent Mappings
AlarmDefinitionMap
public class AlarmDefinitionMap : EntityTypeConfiguration<AlarmDefinition>
{
public AlarmDefinitionMap()
{
this.HasKey(t => t.AlarmDefinitionID);
...
this.ToTable("AlarmDefinition");
this.Property(t => t.AlarmDefinitionID).HasColumnName("AlarmDefinitionID");
...
}
}
AlarmMap
public class AlarmMap : EntityTypeConfiguration<Alarm>
{
public AlarmMap()
{
this.HasKey(t => t.AlarmID);
...
this.ToTable("Alarm");
this.Property(t => t.AlarmID).HasColumnName("AlarmID");
this.Property(t => t.AlarmDefinitionID).HasColumnName("AlarmDefinitionID");
this.Property(t => t.SampleTagID).HasColumnName("SampleTagID");
this.Property(t => t.SampleTime).HasColumnName("SampleTime");
...
this.HasOptional(t => t.AlarmDefinition)
.WithMany(d => d.Alarms)
.HasForeignKey(t => t.AlarmDefinitionID);
}
}
ReasonActionMap
public class ReasonActionMap : EntityTypeConfiguration<ReasonAction>
{
public ReasonActionMap()
{
this.HasKey(t => new { t.Time, t.TagID, t.ReasonActionID });
this.Property(t => t.TagID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.Property(t => t.ReasonActionID).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.ToTable("ReasonAction");
this.Property(t => t.Time).HasColumnName("Time");
this.Property(t => t.TagID).HasColumnName("TagID");
this.Property(t => t.ReasonActionID).HasColumnName("ReasonActionID");
// Relationships
// Not sure if this is correct since the related column names in the Alarm table are SampleTagId, not TagID and SampleTime, not Time. And SampleTagID and SampleTime in the Alarm table are not a primary keys.
// There's an implicit one-to-many relationship between the Alarm and ReasonAction entities.
this.HasRequired(t => t.Alarm)
.WithMany(d => d.ReasonActions)
.HasForeignKey(t => new { t.TagID, t.Time });
this.HasRequired(t => t.ReasonActionDefinition)
.WithMany(d => d.ReasonActions)
.HasForeignKey(t => t.ReasonActionID);
}
}
ReasonActionDefinitionMap
public class ReasonActionDefinitionMap : EntityTypeConfiguration<ReasonActionDefinition>
{
public ReasonActionDefinitionMap()
{
this.HasKey(t => t.ReasonActionID);
...
this.ToTable("ReasonActionDefinition");
this.Property(t => t.ReasonActionID).HasColumnName("ReasonActionID");
...
}
}
Whew! That was a lot of stuff. Anyway, here are some issues with our database and mapping things to EF: 1. No declarative referential integrity – all handled in triggers or legacy application code, 2. In the Alarm table, SampleTagID and SampleTime are not primary keys, yet these two columns are the one-side for an implicit one-to-many relation with the ReasonAction table, 3. Column names between the Alarms and ReasonAction tables do not match (SampleTagID and SampleTime for the Alarm table and Time and TagID for the ReasonAction table).
So, my questions are: A. Given the situation described above, can I make EF code first work with my existing database and tables?, B. How do I need to change my code to make the one-to-many relationship work between the Alarm and ReasonAction tables (so that when I query for Alarms the ReasonActions navigation property is populated with all related records)?, C. Any other suggestions?
Thanks!!!

We ended up ditching EF for now and writing our own custom ADO.NET code.

Related

EF Core - One to many relationship with additional navigation property of same dependent entity type

I'm having trouble configurating my relationships in EF Core. I've been greeted with the following exception -
Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other
FOREIGN KEY constraints
I've trimmed back the entities for this post, but both of these entities have their own table.
public class ApplicationSetupTest
{
public Guid Id { get; set; }
public Guid SchemeId { get; set; }
public string Description { get; set; }
public Guid LatestVersionId { get; set; }
public ApplicationSetupVersionTest LatestVersion { get; set; }
public ICollection<ApplicationSetupVersionTest> VersionHistory { get; set; }
}
public class ApplicationSetupVersionTest
{
public Guid Id { get; set; }
public Guid SetupId { get; set; }
public string Data { get; set; }
public string AuditComment { get; set; }
public Guid PreviousVersionId { get; set; }
}
The ApplicationSetupTest class effectively defines static data with a LatestVersionId that is the key for navigation property LatestVersion.
The ApplicationSetupVersionTest class is the versioned/audited data. Each one of these has a SetupId to link it back to the ApplicationSetupTest to which is refers.
I added the VersionHistory property purely for this post to demonstrate that there could be multiple ApplicationSetupVersionTest on every ApplicationSetupTest. I haven't added an ApplicationSetupTest on the ApplicationSetupVersionTest as this isn't something I expect to need.
My configuration for ApplicationSetupTest is then as follows:
public class ApplicationSetupEntityConfiguration : IEntityTypeConfiguration<ApplicationSetupTest>
{
public void Configure(EntityTypeBuilder<ApplicationSetupTest> builder)
{
builder.Property(t => t.SchemeId).IsRequired();
builder.Property(t => t.Description).IsRequired();
builder.Property(t => t.LatestVersionId).IsRequired();
builder.HasMany(t => t.VersionHistory)
.WithOne()
.HasForeignKey(t => t.SetupId)
.IsRequired();
builder.HasOne(t => t.LatestVersion)
.WithOne()
.HasForeignKey<ApplicationSetupTest>(t => t.LatestVersionId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
builder.HasOne<Scheme>()
.WithMany()
.HasForeignKey(t => t.SchemeId)
.IsRequired();
}
}
The HasMany -> WithOne on VersionHistory is there to define that when I delete a setup, I should delete all version entities.
I assume the second configuration is therefore the area to change. The OnDelete(NoAction) was added following Google searches and I also tried removing the IsRequired() as well as making the LatestVersionId nullable.
I am looking to configure the second relationship so that the LatestVersion property can be included on query.
Any thoughts out there on how to configure such a relationship? Or am I doing something that you wouldn't recommend?
(I will refer to the models as Setup and Version for simplicity).
With your one-to-many configuration -
builder.HasMany(t => t.VersionHistory)
.WithOne()
.HasForeignKey(t => t.SetupId)
.IsRequired();
you have declared Setup as the principal end, and Version as the dependent end, which is correct.
But then you have a LatestVersionId foreign key in Setup, referencing to Version, and configuration of the one-to-one relationship -
builder.HasOne(t => t.LatestVersion)
.WithOne()
.HasForeignKey<ApplicationSetupTest>(t => t.LatestVersionId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired();
trying to configure Setup as the dependent end and Version as the principal end. I'm sure you can see the contradiction.
With the following simplified models -
public class Setup
{
public Guid Id { get; set; }
public string Description { get; set; }
public Version LatestVersion { get; set; }
public ICollection<Version> VersionHistory { get; set; }
}
public class Version
{
public Guid Id { get; set; }
public string Data { get; set; }
// not nullable - every Version must belong to a Setup
public Guid SetupIdHistory { get; set; }
// nullable - not every Version is a latest version
public Guid? SetupIdLatest { get; set; }
}
you can configure them correctly to represent your relationships as -
public void Configure(EntityTypeBuilder<Setup> builder)
{
builder.HasMany(p => p.VersionHistory)
.WithOne()
.HasForeignKey(p => p.SetupIdHistory)
.OnDelete(DeleteBehavior.Cascade) // not required, cascading is default
.IsRequired();
builder.HasOne(p => p.LatestVersion)
.WithOne()
.HasForeignKey<Version>(p => p.SetupIdLatest)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired(false);
}
If you choose not to have a foreign key for the one-to-many relationship, EF will create a nullable one for you and manage the relationship at model level with a shadow property. But for the one-to-one relationship, you must define a foreign key.
public class Version
{
public Guid Id { get; set; }
public string Data { get; set; }
// nullable - not every Version is a latest version
public Guid? SetupId { get; set; }
}
public void Configure(EntityTypeBuilder<Setup> builder)
{
builder.HasMany(p => p.VersionHistory)
.WithOne()
.OnDelete(DeleteBehavior.Cascade)
.IsRequired(); // this will have no effect, the FK will be nullable
builder.HasOne(p => p.LatestVersion)
.WithOne()
.HasForeignKey<Model.Version>(p => p.SetupId)
.OnDelete(DeleteBehavior.NoAction)
.IsRequired(false);
}

Create one to one relationship optional on both sides in EF6

Is there a way to map two entities to have one to one relationship optional on both sides using fluent API in Entity Framework 6?
Code example:
// Subscription (has FK OrderId)
this.HasOptional(t => t.Order)
.WithOptionalDependent(t => t.Subscription)
.HasForeignKey(d => d.OrderId); // does not compile
Context: why would I do this? I work in an existing system where there are payment orders to buy subscriptions. When a order get paid a subscription is created and associated whit it, meaning subscription is optional to order. Also, there are other ways to create subscriptions, meaning order is optional to subscription.
Usually in an one-to-one (or zero) relationship both entities shares the same PK and, in the dependent one, the PK is also specified as FK. Check this link for more info about this. But if you entities not share the same PK, then you can't add a FK property in the dependent entity. If you do that, EF will throw an exception related with the multiplicity saying that it must be *.
About the relationship's configuration, there is only one way to configure an one-to-one relationship with both sides as optional, which it is what you currently have using Fluent Api. This way you can also use the Map method to rename the FK column that EF create by convention in the dependent table by the name that you already have in the Subscription table in your DB.
Update
If you were not tied to an existing database, you could do something like this:
public class Subscription
{
public int SubscriptionId { get; set; }
public int? OrderId { get; set; }
public virtual Order Order { get; set; }
}
public class Order
{
public int OrderId { get; set; }
public int SubscriptionId { get; set; }
public virtual Subscription Subscription { get; set; }
}
And the configuration would be this:
modelBuilder.Entity<Subscription>()
.HasOptional(s => s.Order)
.WithMany()
.HasForeignKey(s=>s.OrderId);
modelBuilder.Entity<>(Order)
.HasOptional(s => s.Subscription)
.WithMany()
.HasForeignKey(s=>s.SubscriptionId);
This way you can work with the OrderIdFK (and SubscriptionId too) like it was a one-to-one relationship. The problem here is you have to set and save both associations separately.
Kindly try this code in the database context class
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Subscription>()
.HasOptional(x => x.Order)
.WithOptionalPrincipal()
.Map(x => x.MapKey("SubscriptionId"));
modelBuilder.Entity<Order>()
.HasOptional(x => x.Subscription)
.WithOptionalPrincipal()
.Map(x => x.MapKey("OrderId"));
}
My test models are as follows
public class Order
{
[Key]
public int OrderId { get; set; }
public string Description { get; set; }
public virtual Subscription Subscription { get; set; }
}
public class Subscription
{
[Key]
public int SubscriptionId { get; set; }
public virtual Order Order { get; set; }
}
Edit:
I did a reverse engineering to database trying to reach the required code structure by using double 1 to many relation to work like you want. The generated code is like the following. However, It is bad idea to do so.
public partial class Order
{
public Order()
{
this.Subscriptions = new List<Subscription>();
}
public int OrderId { get; set; }
public string Description { get; set; }
public Nullable<int> SubscriptionId { get; set; }
public virtual Subscription Subscription { get; set; }
public virtual ICollection<Subscription> Subscriptions { get; set; }
}
public partial class Subscription
{
public Subscription()
{
this.Orders = new List<Order>();
}
public int SubscriptionId { get; set; }
public Nullable<int> OrderId { get; set; }
public virtual ICollection<Order> Orders { get; set; }
public virtual Order Order { get; set; }
}
public class OrderMap : EntityTypeConfiguration<Order>
{
public OrderMap()
{
// Primary Key
this.HasKey(t => t.OrderId);
// Properties
// Table & Column Mappings
this.ToTable("Orders");
this.Property(t => t.OrderId).HasColumnName("OrderId");
this.Property(t => t.Description).HasColumnName("Description");
this.Property(t => t.SubscriptionId).HasColumnName("SubscriptionId");
// Relationships
this.HasOptional(t => t.Subscription)
.WithMany(t => t.Orders)
.HasForeignKey(d => d.SubscriptionId);
}
}
public class SubscriptionMap : EntityTypeConfiguration<Subscription>
{
public SubscriptionMap()
{
// Primary Key
this.HasKey(t => t.SubscriptionId);
// Properties
// Table & Column Mappings
this.ToTable("Subscriptions");
this.Property(t => t.SubscriptionId).HasColumnName("SubscriptionId");
this.Property(t => t.OrderId).HasColumnName("OrderId");
// Relationships
this.HasOptional(t => t.Order)
.WithMany(t => t.Subscriptions)
.HasForeignKey(d => d.OrderId);
}
}
public partial class EFOrdersContextContext : DbContext
{
static EFOrdersContextContext()
{
Database.SetInitializer<EFOrdersContextContext>(null);
}
public EFOrdersContextContext()
: base("Name=EFOrdersContextContext")
{
}
public DbSet<Order> Orders { get; set; }
public DbSet<Subscription> Subscriptions { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Configurations.Add(new OrderMap());
modelBuilder.Configurations.Add(new SubscriptionMap());
}
}

Entity Framework codefirst issueUnable to determine the principal end of an association between the types

So I'm trying to use the MVC 4 internet application template and the UserProfile database tables it creates for accounts and then add tables that have dependencies on the UserProfile table for additional information.
The model would be UserProfile 0 ---> 1 UserType1 and UserProfile 0 ----> UserType2
where the userprofile table may have a dependent record in UserType1 and may have a dependent record in UserType2 and if there is an entry in either UserType1 or UserType2 its primary key is a foreign key that is the UserId from User Profiles
The POCO is:
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public int type { get; set; }
public virtual UserType1 UserType1 { get; set; }
public virtual UserType2 UserType2 { get; set; }
public class UserType1
{
[key,ForeignKey("UserProfile")]
public virtual int UserId {get;set;}
public int myval {get;set;}
public UserProfile UserProfile {get; set;}
}
public class UserType2 //same as usertype 1
I've tried adding model mapping statements but to no avail
Model mapping data for user profile:
public class UserProfileMap : EntityTypeConfiguration<UserProfile>
{
public UserProfileMap()
{
// Primary Key
this.HasKey(t => t.UserId);
// Properties
this.Property(t => t.Email)
.IsRequired()
.HasMaxLength(56);
this.Property(t => t.UserName)
.IsRequired()
.HasMaxLength(50);
// Table & Column Mappings
this.ToTable("UserProfile");
this.Property(t => t.UserId).HasColumnName("UserId");
this.Property(t => t.Email).HasColumnName("Email");
this.Property(t => t.UserName).HasColumnName("UserName");
this.Property(t => t.UserType).HasColumnName("UserType");
this.HasOptional(e => e.UserType1).WithRequired();
The model mapping data for usertypes looks like this:
public class UserType1 : EntityTypeConfiguration<UserType1>
{
public UserType1Map()
{
// Primary Key
this.HasKey(t => t.UserId);
// Properties
this.Property(t => t.UserId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
this.HasRequired(t => t.UserProfile).WithOptional();
this.Property(t => t.Company)
.IsRequired()
.HasMaxLength(50);
// Table & Column Mappings
this.ToTable("UserType1");
this.Property(t => t.UserId).HasColumnName("UserId");
this.Property(t => t.Company).HasColumnName("Company");
// Relationships
this.HasRequired(t => t.UserProfile).WithOptional();
}
}
But I always get this error Unable to determine the principal end of an association between the types 'myApp.Models.UserType1' and 'myApp.Models.UserProfile'. The principal end of this association must be explicitly configured using either the relationship fluent API or data annotations.
what did I miss?
Configure the relationship for only one entity (in your case, in UserProfileMap). Explicitly specify the property in the .WithRequired() call as well. Here's demo code that worked for me:
modelBuilder.Entity<SharedKeyRequired>()
.HasOptional( skr => skr.SharedKeyOptional )
.WithRequired( sko => sko.SharedKeyRequired );
public class SharedKeyRequired
{
public int SharedKeyRequiredId { get; set; }
public virtual SharedKeyOptional SharedKeyOptional { get; set; }
}
public class SharedKeyOptional
{
public int SharedKeyOptionalId { get; set; }
public virtual SharedKeyRequired SharedKeyRequired { get; set; }
}
Moho, I voted your answer as correct but I thought I would put MVC equivalent source here for those that might be confused by the verbage.
Desired end result is using the MVC AccountModel and adding code-first tables which have a foreignkey as their primary keys to extend the UserProfile table with an optional 1 to 1 relationship
Modify your user profile class to add a virtual reference to your new table
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }
public string UserName { get; set; }
public virtual UserInfo UserInfo { get; set; }
}
create your new table I chose to use Data Notation you could specify this in modelBuilder as
modelBuilder.Entity().HasKey(k => k.UserId);
modelBuilder.Entity().Property(ui => ui.UserId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
public class UserInfo
{
[Key,ForeignKey("UserProfile")] //use above or specify this
public int UserId { get; set; }
public virtual UserProfile UserProfile { get; set; }
public int somevalue { get; set; }
public string name { get; set; }
}
override your OnModelCreating member of your context class and specify the relationship as Moho stated
public class UsersContext : DbContext
{
public UsersContext()
: base("DefaultConnection")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// modelBuilder.Entity<UserInfo>().HasKey(k => k.UserId);
// modelBuilder.Entity<UserInfo>().Property(ui => ui.UserId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<UserProfile>().HasOptional(ui => ui.UserInfo).WithRequired(up => up.UserProfile);
base.OnModelCreating(modelBuilder);
}
public DbSet<UserProfile> UserProfiles { get; set; }
public DbSet<UserInfo> UserInfoes { get; set; }
}

How to model one way one-to-one in Fluent EF?

Let's say I have the following entities:
Box
Id
Crank crank // has one required relationship
Crank
Id // does not care about the box
What is the proper way to define BoxMap? Is this sufficient? Or do I need WithRequiredPrincipal (which I have no idea what that does):
HasKey(t => t.Id);
ToTable("Boxes")
Property(t=>t.Id).HasColumnName("Id")
Property(t=>t.CrankId).HasColumnName("Crank_Id")
HasRequired(t=>t.Crank)
NOTE: Any good resources on learning fluent api are welcome. Thanks.
public class Context : DbContext
{
public DbSet<Box> Boxes { get; set; }
public DbSet<Crank> Cranks { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Box>()
.HasRequired(m => m.Crank)
.WithOptional()
.Map(m => m.MapKey("Crank_Id"));
base.OnModelCreating(modelBuilder);
}
}
public class Box
{
public int Id { get; set; }
public Crank Crank { get; set; } // has one required relationship
}
public class Crank
{
public int Id { get; set; }
}
You don't need to specify this:
HasKey(t => t.Id);
ToTable("Boxes")
Property(t=>t.Id).HasColumnName("Id")
Property(t=>t.CrankId).HasColumnName("Crank_Id")
HasRequired(t=>t.Crank)
It will be detected by convention of EF.

Setting up code first associations in entity frame 4.1 with multiple tables

Sorry if this is a simple thing, but I'm just learn EF and can't seem to find my answer (or maybe it's just understand what I'm finding).
I have three existing database tables as follows:
Order:
int OrderNo (Primary Key generated by program)
...
OrderDetails:
int OrderNo (Foreign key from Order=>OrderNo; but part of primary key for OrderDetails)
int DetailNo (Part of primary key; generated by program)
...
OrderResults:
int OrderNo (Key from Detail=>OrderNo; but part of primary key for OrderResults)
int DetailNo (Key from Detail=>DetailNo; but part of primary key fro OrderResult)
int ResultNo (Part of primary key; generated by program)
...
My Entities are defined as:
public Class Order
{
public int OrderNo { get; set; }
publice virtual ICollection<Detail> Details { get; set; }
}
public Class Detail
{
public int OrderNo { get; set; }
public int DetailNo { get; set; }
public virtual Order Order { get; set; }
public virtual ICollection<Result> Results { get; set; }
}
public Class Result
{
public int OrderNo { get; set; }
public int DetailNo { get; set; }
public int ResultNo { get; set; }
public virtual Detail Detail { get; set; }
}
So how would you define these key and associations using the fluent API? Currently I'm getting the OrderDetails linked to the Order correctly, but not getting the correct OrderResults.
You can try something like this:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Mapping for Order
modelBuilder.Entity<Order>()
.HasKey(o => o.OrderNo);
modelBuilder.Entity<Order>()
.Property(o => o.OrderNo)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<Order>()
.HasMany(o => o.Details)
.WithRequired(d => d.Order)
.HasForeignKey(d => d.OrderNo);
// Mapping for Detail
modelBuilder.Entity<Detail>()
.HasKey(d => new { d.OrderNo, d.DetailNo });
// I believe, setting to DatabaseGeneratedOption.None is not necessary
// for composite keys
modelBuilder.Entity<Detail>()
.HasMany(d => d.Results)
.WithRequired(r => r.Detail)
.HasForeignKey(r => new { r.OrderNo, r.DetailNo });
// Mapping for Result
modelBuilder.Entity<Result>()
.HasKey(r => new { r.OrderNo, r.DetailNo, r.ResultNo });
}
Fluent API is quite verbose in this example. You can all the mappings also define with data annotations.