代码之家  ›  专栏  ›  技术社区  ›  Kgn-web

使用Fluent API的EF核心中的一对一关系[副本]

  •  1
  • Kgn-web  · 技术社区  · 6 年前

    我正在使用 EF Core 2.1

    如何在EF核心中映射一对一关系。我有 Customer 和; Course 一个客户将拥有一个课程的域实体。

    这就是我的客户&coursePoco的样子。

    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; }
    }
    

    我在用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
        }
    }
    

    因为它是一对一关系,所以我不想在联系人中创建一个额外的键(fk-customerid)。

    主要要求: 我想定义 Id (当然) PK + FK &在此关系中,客户是父实体。

    如果我是基于配置的迁移,我将按如下方式进行:

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

    我想在ef core中使用fluent API做同样的事情??

    谢谢!!

    2 回复  |  直到 6 年前
        1
  •  0
  •   itminus    6 年前

    正如其他答案所指出的,关键是使用 HasForeignKey<>() 配置外键的方法。

    但是要小心,应该在依赖实体而不是主体实体上设置外键。

    具体操作方法:

    将导航属性添加到 Course 对于 Customer

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

    现在设置 Course.Id 作为一个 FK 它引用了 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; }
    }
    

    生成的SQL脚本是:

    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
    
        2
  •  0
  •   Manoj Choudhari    6 年前

    下面类似的内容应该会有所帮助。hasone方法与with 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);
    }