将复合表映射到EF Core中的默认值表

时间:2019-05-11 21:02:33

标签: c# entity-framework-core

我在数据库中有一个简单的结构:

CREATE TABLE user_categories (
    user_id INT NOT NULL,
    category_id INT NOT NULL,
    PRIMARY KEY (user_id, category_id)
);

CREATE TABLE user_defaults (
    user_id INT NOT NULL,
    category_id INT NOT NULL,
    PRIMARY KEY (user_id),
    FOREIGN KEY (user_id, category_id) REFERENCES user_categories (user_id, category_id)
);

这里的意图是为用户分配了一组类别,并且存在一个带有默认表的表(可能有其他列)

无论我如何将其映射到EF Core,我总是最终在user_categories表中获得额外的列。

我的UserCategory班:

using System.ComponentModel.DataAnnotations.Schema;

namespace EMMA.Authorization.Domain.Entities
{
    public class UserCategory
    {
        public int UserId { get; set; }    
        [ForeignKey(nameof(UserId))]
        public User User { get; set; }

        public int CategoryId { get; set; }
        [ForeignKey(nameof(CategoryId))]
        public Category Category { get; set; }

        public UserDefaults UserDefaults { get; set; }
    }
}

UserDefaults

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;

namespace EMMA.Authorization.Domain.Entities
{
    public class UserDefaults
    {
        public int UserId { get; set; }
        public int CategoryId { get; set; }

        public virtual ICollection<UserCategory> UserCategories { get; set; }
    }
}

OnModelCreating方法应配置关系:

modelBuilder.Entity<UserCategory>().HasKey(s => new { s.UserId, s.CategoryId });
modelBuilder.Entity<UserDefaults>().HasKey(s => s.UserId);
modelBuilder.Entity<UserDefaults>()
    .HasMany(s => s.UserCategories)
    .WithOne(s => s.UserDefaults)
    .HasForeignKey(s => new { s.UserId, s.CategoryId })
    .IsRequired();

但是,当我尝试创建迁移时却遇到了例外情况:

  

具有外键属性{'UserId':int,'CategoryId':int}的从'UserCategory.UserDefaults'到'UserDefaults.UserCategories'的关系无法针对主键{'UserId':int},因为它不是兼容。为此关系配置一个主键或一组兼容的外键属性。

如何在EF Core中配置SQL中所示的这种关系?

2 个答案:

答案 0 :(得分:0)

user_catagories对象应具有组合键。通过将另一个表中的FK作为第一个表上的复合键,您已经在暗示这一点。 EF抱怨,因为这实际上不是事实。您可以通过将两个成员都注释为主要成员来解决此问题,

public class UserCatagory
{
      [Key, Column(Order = 0)]
      public int UserId { get; set; }

      [Key, Column(Order = 1)]
      public int CategoryId { get; set; }

      // Etc...
}

答案 1 :(得分:0)

我实际上意识到我确实声明了错误的关系,它不是一对多的,而是一对一的。声明以下映射将按预期工作:

modelBuilder.Entity<UserCategory>()
    .HasOne(s => s.UserDefaults)
    .WithOne(s => s.UserCategory)
    .HasForeignKey<UserDefaults>(s => new { s.UserId, s.CategoryId })
    .IsRequired();