I'm using Code First CTP 5. I have a fairly simple setup between a parent table and child tables
Create table testA (
id int not null identity(1,1),
stuff varchar(200),
primary key (id)
);
go
create table testB (
id int not null
foreign key references testA(id),
morestuff varchar(200),
primary key (id)
);
go
To refer to these table using Code First, we have the following construct:
namespace Test.Models
{
public class TestEntities : DbContext
{
public DbSet<testa> testa { get; set; }
public DbSet<testb> testb { get; set; }
protected override void OnModelCreating(System.Data.Entity.ModelConfiguration.ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<testa>().ToTable("testa");
modelBuilder.Entity<testa>()
.Property(p => p.id)
.HasDatabaseGenerationOption(DatabaseGenerationOption.Identity);
modelBuilder.Entity<testb>().ToTable("testb");
}
}
public class testa
{
public int id { get; set; }
public String stuff { get; set; }
public virtual testb testb { get; set; }
}
public class testb
{
public int id { get; set; }
public string morestuff { get; set; }
public virtual testa testa { get; set; }
}
}
When I try to add a record to testa, I get the error "Cannot insert explicit value for identity column in table 'testA' when IDENTITY_INSERT is set to OFF."
Ok. Strike 1 to Code First for not recognizing that Id is an identity column. We can fix this, so we tell CodeFirst that testa.id is an identity:
modelBuilder.Entity<testa>()
.Property(p => p.id)
.HasDatabaseGenerationOption(DatabaseGenerationOption.Identity);
That done we run it again and get another error: "A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'id'". So - what's wrong with this picture?
What am I doing wrong and how do I fix it???
In a 1:1 association, Code First recognize one of the entities as principal and the other one as dependent. Then it makes the principal PK as identity and you need to take care of a valid unique PK when inserting into the dependent table. In your case it picks testb
as the principal but it looks like that you want testa
to be the principal end in this association. This could be achieved by using fluent API and basically giving hint to Code First about which one is principal and which one is dependent:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<testb>()
.HasRequired(b => b.testa)
.WithOptional(a => a.testb);
}
For more information, take a look at this article:
Associations in EF Code First CTP5: Part 2 – Shared Primary Key Associations