Sto usando EF Core 2.1
Come mappare la relazione one-to-one in EF Core. Ho un'entità di dominio Customer
& Course
cui un cliente avrà un corso.
Questo è il mio aspetto del mio cliente e del mio corsoPOCO.
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; }
}
Sto usando 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
}
}
Poiché è una relazione uno a uno, non voglio creare una chiave extra in Contact (FK -CustomerId),
Requisito principale: - Voglio definire Id
(in corso) come PK + FK
e in questa relazione il Cliente è un'entità padre.
Come se fossi una migrazione basata sulla configurazione, farei come segue: -
public class Course
{
[Key]
[ForeignKey("Customer")]
public int Id { get; set; }
public string Name { get; set; }
public virtual Customer Customer { get; set; }
}
stessa cosa mi piacerebbe fare usando l'API Fluent in EF Core ??
Grazie!!
Come indicato da altre risposte, il punto chiave è utilizzare il HasForeignKey<>()
per configurare una chiave esterna.
Ma fai attenzione che la chiave esterna debba essere impostata sull'entità dipendente, invece che sull'entità principale.
Come nei dettagli:
Aggiungi una proprietà di navigazione a Course
per Customer
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
public Course Course {get;set;}
}
e ora impostare il Course.Id
come un FK
che fa riferimento al 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; }
}
gli script sql generati sono:
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
Qualcosa di simile a sotto dovrebbe aiutare. Il metodo HasOne è incatenato con WithOne che potrebbe aiutare a stabilire una relazione one-to-one:
public class Customer
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Course
{
public int Id { get; set; }
public string CourseName { get; set; }
public int CustomerId {get;set;}
public virtual Customer Customer { get; set; }
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>()
.HasOne(a => a.Customer)
.WithOne(b => b.Course)
.HasForeignKey<Course>(b => b.CustomerId);
}