实体框架:如果引用列是标识列,则无法创建级联外键。无法创建约束或索引

时间:2019-10-15 19:36:37

标签: entity-framework .net-core entity-framework-core ef-migrations

我在尝试创建与数据透视表的一对一关系时遇到问题。这些是我的模特

    public class StudentCourse
    {
        public int Id { get; set; }
        public int StudentId { get; set; }
        public virtual Student Student { get; set; }
        public int CourseId { get; set; }
        public virtual Course Course { get; set; }
    }

    public class Student
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public virtual IList<StudentCourse> StudentCourses { get; set; }
    }

    public class Course
    {
        public int Id { get; set; }
        public string CourseName { get; set; }
        public string Description { get; set; }
        public virtual IList<StudentCourse> StudentCourses { get; set; }
    }

    public class ExamResult
    {
        public int Id { get; set; }
        public int Marks { get; set; }
        public int TotalMarks { get; set; }
        public virtual StudentCourse StudentCourse { get; set; }
    }

这是模型构建器配置,我在其中定义了学生和课程之间的多对多关系

            protected override void OnModelCreating(ModelBuilder modelBuilder)
            {
                modelBuilder.Entity<StudentCourse>().HasKey(sc => new { sc.StudentId, sc.CourseId });
                modelBuilder.Entity<StudentCourse>().HasAlternateKey(e => e.Id);
                modelBuilder.Entity<StudentCourse>().Property(e => e.Id).ValueGeneratedOnAdd();

                modelBuilder.Entity<StudentCourse>()
                    .HasOne(sc => sc.Student)
                    .WithMany(s => s.StudentCourses)
                    .HasForeignKey(sc => sc.StudentId)
                    .OnDelete(DeleteBehavior.Cascade);

                modelBuilder.Entity<StudentCourse>()
                    .HasOne(sc => sc.Course)
                    .WithMany(s => s.StudentCourses)
                    .HasForeignKey(sc => sc.CourseId)
                    .OnDelete(DeleteBehavior.Cascade);
            }

这是我在运行迁移时收到的错误消息

Failed executing DbCommand (11ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [StudentCourses] (
    [StudentId] int NOT NULL,
    [CourseId] int NOT NULL,
    [Id] int NOT NULL IDENTITY,
    CONSTRAINT [PK_StudentCourses] PRIMARY KEY ([StudentId], [CourseId]),
    CONSTRAINT [AK_StudentCourses_Id] UNIQUE ([Id]),
    CONSTRAINT [FK_StudentCourses_Courses_CourseId] FOREIGN KEY ([CourseId]) REFERENCES [Courses] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_StudentCourses_ExamResults_Id] FOREIGN KEY ([Id]) REFERENCES [ExamResults] ([Id]) ON DELETE CASCADE,
    CONSTRAINT [FK_StudentCourses_Students_StudentId] FOREIGN KEY ([StudentId]) REFERENCES [Students] ([Id]) ON DELETE CASCADE
);

Cascading foreign key 'FK_StudentCourses_ExamResults_Id' cannot be created where the referencing column 'StudentCourses.Id' is an identity column.
Could not create constraint or index. See previous errors.

基本上,我试图指向ExamResult表中的StudentCourse记录,但是由于某种原因,它失败了。有人知道吗?

1 个答案:

答案 0 :(得分:1)

这是EF Core问题/错误,似乎已在EF Core 3.0中修复。 Id的备用键StudentCourse在某种程度上混淆了EF Core 3.0之前的版本约定,而不是从ExamResultStudentCourse的预期多对一关系,它错误地假设一个与ExamResult为主体,StudentCourse为从属的一对一关系,因此ExamResult中缺少FK,而StudentCourse中没有FK。

解决方案是通过流利的API显式配置所需的关系:

modelBuilder.Entity<ExamResult>()
    .HasOne(e => e.StudentCourse)
    .WithMany();

请注意,这将在ExamResult中引用StudentCourse的组合PK创建一个可选的组合FK。如果要通过StudentCourse的备用键来关联,则应使用HasPrincipalKey API对其进行配置:

modelBuilder.Entity<ExamResult>()
    .HasOne(e => e.StudentCourse)
    .WithMany()
    .HasPrincipalKey(sc => sc.Id);