繁体   English   中英

如何防止实体框架创建双外键

[英]How to prevent Entity Framework from creating double Foreign Keys

我在使用代码先从我的实体创建数据库时遇到了麻烦。 请考虑两个类。 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 Framework似乎并没有重组该约定,而是将courseTnId映射为一个属性。

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

在此处输入图片说明

有没有一种方法可以使Entity Framework识别ChapterTn类中courseTnId的常规指定FK?

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

另外,你可以用力FK识别与属性CourseTnIdChapterTn类。
[ForeignKey("CourseTn"), Column(Order = 0)]

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

由于某些原因,您决定偏离实体框架的代码优先约定 ,因此不得不使用属性或流畅的API对此进行更正。

为什么您的“多对多”集合类列表而不是ICollections? Course.Chapters[4]真的Course.Chapters[4]吗? 此外,您确定要限制自己使用包含真正章节列表的课程吗? 当然不是,因为在您的课程内部甚至没有章节列表。 内部有两个带有外键的表。 因此它不是列表。 最多可以添加一个元素,并可以请求元素的数量:不是列表,而是ICollection。

出于某种原因,您课程的主键类型是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
}

因为我遵循了实体框架一对多的约定 ,所以这是所有实体框架需要了解的用于配置两个表以及主键和外键的所有知识。 不需要属性,也不需要流利的API。

我还将主键更改为更常规的类型,如果您确实有很好的论据可以按自己的方式操作,请尝试一下并查看它是否有效。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM