Reputation: 1718
I currently have a one-to-one relationship between 2 entities. The primary entity looks like this:
public class PrimaryEntity
{
// primary key
public Guid Id { get; set; }
// some other properties...
public RelatedEntity Related { get; set; }
}
And my related entity looks like this:
public class RelatedEntity
{
// both the primary and foreign key
public Guid PrimaryEntityId { get; set; }
// some other properties
}
So my question is, how could this one-to-one relationship be defined using the EF 6 fluent api (can't use annotations)? I've tried many different variations of config settings for this, all with no luck. Is it even possible to define a one sided relationship like this, and have the key names different? Is the fact that my RelatedEntity is using the same property for both primary and foreign keys?
Any help is appreciated.
UPDATE:
I was able to resolve the issue. The culprit was in the constructor of the PrimaryEntity I was setting Related = new RelatedEntity. I guess EF doesn't like this. I found that all 3 answers provided worked pretty much the same otherwise. Thanks for everyone's help.
Upvotes: 0
Views: 802
Reputation: 146
public class PrimaryEntity
{
// primary key
public Guid Id { get; set; }
// some other properties...
public RelatedEntity Related { get; set; }
}
public class RelatedEntity
{
// both the primary and foreign key
public Guid PrimaryEntityId { get; set; }
// some other properties
}
//mapping
//configure the primary key as mentioned above
modelBuilder.Entity<RelatedEntity>()
.HasKey(t => t.PrimaryEntityId );
modelBuilder.Entity<PrimaryEntity>()
.HasRequired(p => p.Related )
.WithRequiredPrincipal(); //empty parenthesis for one sided navigation.
Not tested - off the top of my head...
Upvotes: 1
Reputation: 4876
In RelatedEntity
class you also need to define a navigation property, which points to PrimaryEntity
class:
public class RelatedEntity
{
// both the primary and foreign key
public Guid PrimaryEntityId { get; set; }
public PrimaryEntity Primary { get; set; }
// some other properties
}
Then you may use it to configure your one-to-one relationship in OnModelCreating
method of your custom DbContext
class:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<RelatedEntity>().HasKey(e => e.PrimaryEntityId);
modelBuilder.Entity<RelatedEntity>().HasRequired(re => re.Primary).WithOptional(pe => pe.Related);
}
Note that here RelatedEntity
's PrimaryEntityId
property is explicitly configured to be a primary key because it's name in your case is out of default primary key naming convention.
And here is a resulting code first migration, which shows that you get exactly what you need:
CreateTable(
"dbo.PrimaryEntities",
c => new
{
Id = c.Guid(nullable: false),
})
.PrimaryKey(t => t.Id);
CreateTable(
"dbo.RelatedEntities",
c => new
{
PrimaryEntityId = c.Guid(nullable: false),
})
.PrimaryKey(t => t.PrimaryEntityId)
.ForeignKey("dbo.PrimaryEntities", t => t.PrimaryEntityId)
.Index(t => t.PrimaryEntityId);
Upvotes: 1
Reputation: 58
Yes you can configure a one-to-one relationship with EF fluent api.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Configure StudentId as PK for StudentAddress
modelBuilder.Entity<StudentAddress>()
.HasKey(e => e.StudentId);
// Configure StudentId as FK for StudentAddress
modelBuilder.Entity<Student>()
.HasOptional(s => s.StudentAddress) // Mark StudentAddress is optional for Student
.WithRequired(ad => ad.Student); // Create inverse relationship
}
Upvotes: 1