Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

One to one relation in EF Core using Fluent API [duplicate]

I am using EF Core 2.1

How to map one-to-one relationship in EF Core. I have Customer & Course domain entity where one customer will have one Course.

This is my how my Customer & CoursePOCO looks like.

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }

}

public class Course
{
    public int Id { get; set; }
    public string CouseName { get; set; }
    public virtual Customer Customer { get; set; }
}

I am using FluentAPI.

 public class CourseConfiguration : IEntityTypeConfiguration<Course>
{
    public void Configure(EntityTypeBuilder<Parent> builder)
    {
        builder.HasKey(x => x.Customer.Id) //not allowing -> throws error
        //The properties expression 'x => Convert(x.Customer.Id, Object)' is not valid. 
        // The expression should represent a simple property access: 't => t.MyProperty'. 
        // When specifying multiple properties use an anonymous type: 't => new { t.MyProperty1, t.MyProperty2 }'. 
        // Parameter name: propertyAccessExpression
    }
}

Since it's one to one relation, I don't want to create an extra key in Contact (FK -CustomerId),

Primary requirement:- I want to define Id (in Course) as PK + FK & in this relation Customer is parent entity.

Like if I was Configuration based Migration, I would do as follows:-

public class Course
{
    [Key]
    [ForeignKey("Customer")]
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Customer Customer { get; set; }
 }

same thing I would like to do using Fluent API in EF Core??

Thanks!!

like image 907
Kgn-web Avatar asked Jan 26 '23 23:01

Kgn-web


1 Answers

As other answers point out, the key point is to use use the HasForeignKey<>() method to configure a foreign key.

But be careful that the foreign key should be set on the dependent entity, instead of the principal entity.

How to in details:

Add a navigation property to Course for Customer

public class Customer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Course Course {get;set;} 
}

and now set the Course.Id as a FK that references the Customer.Id

public class AppDbContext : DbContext
{
    public AppDbContext (DbContextOptions<AppDbContext> options)
        : base(options)
    {
    }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder.Entity<Customer>(entity=>
        {
            entity.HasOne(customer=>customer.Course)
                .WithOne(course=> course.Customer)
                .HasForeignKey<Course>(course=>course.Id); 
        });
    }

    public DbSet<App.Models.Customer> Customer { get; set; }
    public DbSet<App.Models.Course> Courses{ get; set; }
}

the generated sql scripts is :

CREATE TABLE [Customer] (
    [Id] int NOT NULL IDENTITY,
    [Name] nvarchar(max) NULL,
    CONSTRAINT [PK_Customer] PRIMARY KEY ([Id])
);

GO

CREATE TABLE [Courses] (
    [Id] int NOT NULL,
    [CouseName] nvarchar(max) NULL,
    CONSTRAINT [PK_Courses] PRIMARY KEY ([Id]),
    CONSTRAINT [FK_Courses_Customer_Id] FOREIGN KEY ([Id]) REFERENCES [Customer] ([Id]) ON DELETE CASCADE
);

GO
like image 115
itminus Avatar answered Feb 23 '23 00:02

itminus