如何防止Entity Framework创建双外键

时间:2018-02-07 18:53:30

标签: c# entity-framework ef-code-first

我首先使用代码从我的实体创建数据库时遇到问题。请考虑这两个班级。 CourseTn类

    public class CourseTn
{
    // Pk
    public CourseLevel CourseTnId { get; set; }

    // Properties
    public string Title { get; set; }
    public virtual List<CourseTnImage> CourseImage { get; set; }
    public virtual List<ChapterTn> Chapters { get; set; }

    public AdministratorTnAccount AdministratorTnAccount { get; set; }
    public Guid? AdministratorTnAccountId { get; set; }

    public ClientTnAccount ClientTnAccount { get; set; }
    public Guid? ClientTnAccountId { get; set; }

}

和ChapterTn类

public class ChapterTn
{
    // Pk
    public int ChapterTnId { get; set; }

    // Properties
    public string ChapterName { get; set; }
    public virtual List<ChapterTnImage> ChapterImage { get; set; }
    public virtual List<SectionTn> Sections { get; set; }

    // FK

    public virtual CourseTn CourseTn { get; set; }
    public CourseLevel CourseTnId { get; set; }
}

courseTnId在chapterTn类中指定为外键。第一个问题是,Entitiy框架似乎没有将这个惯例作为记录,而是将courseTnId映射为一个预言。

第二个问题是Enitity Framework为courseTn创建了两个FK,一个为null,另一个不为null。请看下面的图片

enter image description here

有没有办法让make Entity Framework在chapterTn类中识别courseTnId的常规指定FK?

2 个答案:

答案 0 :(得分:0)

您的PK不能是复杂类型CourseLevel。你的FK也一样。试试以下内容:

    public class CourseTn
    {
        // Pk
        public int CourseTnId { get; set; }

        // Properties
        public string Title { get; set; }
        public virtual List<CourseTnImage> CourseImage { get; set; }
        public virtual List<ChapterTn> Chapters { get; set; }

        public AdministratorTnAccount AdministratorTnAccount { get; set; }
        public Guid? AdministratorTnAccountId { get; set; }

        public ClientTnAccount ClientTnAccount { get; set; }
        public Guid? ClientTnAccountId { get; set; }

    }

    public class ChapterTn
    {
        // Pk
        public int ChapterTnId { get; set; }

        // Properties
        public string ChapterName { get; set; }
        public virtual List<ChapterTnImage> ChapterImage { get; set; }
        public virtual List<SectionTn> Sections { get; set; }

        // FK
        public virtual CourseTn CourseTn { get; set; }
        public int CourseTnId { get; set; }
    }

您还可以在CourseTnId班级的ChapterTn上使用属性强制进行FK识别 [ForeignKey("CourseTn"), Column(Order = 0)]

答案 1 :(得分:0)

您计划在CourseChapter之间设置一对多关系:每个Course都有零个或多个Chapters,每个Chapter属于只有一个Course

出于某种原因,您决定偏离the entity framework code-first conventions,因此您必须使用属性或流畅的API来纠正此问题。

为什么你的“to-many”集合类列出而不是ICollections? Course.Chapters[4]真的有意义吗?此外,您确定要将自己限制在具有真正的章节列表的课程中吗?当然不是,因为你的课程内部甚至没有章节列表。在内部有两个带外键的表等。所以它不是List。最重要的是你可以添加一个元素,并且可以要求元素的数量:不是列表,而是ICollection。

由于某种原因,课程主键的类型是CourseLevel。您确定在您的设计中,两门课程可能具有相同的CourseLevel是不可想象的吗?你确定,在将课程添加到数据库之前,你不知道它的CourseLevel吗?课程永远不会变得更难或更容易,从而改变其CourseLevel?尝试使用数据库标识符做一些棘手的事情会带来什么好处?

此外,我认为这是你的问题的原因:虽然你给你的章节一个值CourseId,你忘了告诉实体框架这是本章课程的外键。

以下内容足以解决您的所有问题。

class Course
{
    public int Id {get; set;}
    // every Course has zero or more Chapters:
    public virtual ICollection<Chapter> Chapters {get; set;}

    // other properties:
    public CourseLevel Level {get; set;}
    ...
}

class Chapter
{
    public int Id {get; set;}

    // every Chapter belongs to exactly one Course using foreign key
    public int CourseId {get; set;}
    public virtual Course Course {get; set;}

    ... // other properties
}

因为我遵循the entity framework one-to-many conventions,所以这是实体框架需要知道的所有配置两个表以及主键和外键。不需要属性,也不需要流畅的API。

我还将主键更改为更传统的类型,如果你真的有充分的理由来保持它的方式,试试看它是否有效。