gpt4 book ai didi

【EFCore】主从实体关系与常见实体关系的区别

转载 作者:我是一只小鸟 更新时间:2023-07-15 22:31:17 28 4
gpt4 key购买 nike

上次老周扯了有关主、从实体的话题,本篇咱们再挖一下,主、从实体之间建立的关系,跟咱们常用的一对1、一对多这些关系之间有什么不同.

先看看咱们从学习数据库开始就特熟悉的常用关系——多对多、一对1、一对多说起。数据实体之间会建立什么样的关系,并不是规则性的,而是要看数据的功能。比如你家养的狗狗和水果(你家狗狗可能不吃水果,但老周养的动物基本是什么都吃的,因为从它们幼年起,老周就训练它们,对食物要来者不拒,就算哪天它们不想跟着老周混,出去流浪也不会饿死,适应性更强).

假设:

1、你的数据是以狗狗为主,那么一条狗狗会吃多种水果。即狗狗对水果是一对多; 。

2、你的数据以水果为主,每种水果单独记录,然后在另一个表中记录水果被哪几条狗喜欢。例:雪梨,狗Y和狗B都喜欢吃。于是水果对狗狗也可以是一对多的关系.

再假设你有个幼儿园学生尿床登记表,表中记录每次尿床的时间、床号等。每一条尿床记录都有一个字段,引用自学生表,代表是哪们同学尿床了。多条尿床记录可能都是同一个人的,比如,小明一周有三次尿床。这样,尿床记录和学生之间可以是多对一关系了.

数据是为咱们人服务的,因此实体之间建立什么样的关系,得看咱们人类是怎么理解,以及这些实体的用途.

还是用上一篇水文中的学生 - 作业的例子.

                          
                            public
                          
                          
                            class
                          
                          
                             Student
{
    
                          
                          
                            //
                          
                          
                             主键:学生ID
                          
                          
                            public
                          
                          
                            int
                          
                           StuID { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             学生姓名
                          
                          
                            public
                          
                          
                            string
                          
                          ? Name { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             年级
                          
                          
                            public
                          
                          
                            ushort
                          
                           Grade { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             作业(导航属性)
                          
                          
                            public
                          
                           IEnumerable<Homework> Homeworks { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          ; } = 
                          
                            new
                          
                           List<Homework>
                          
                            ();
}


                          
                          
                            public
                          
                          
                            class
                          
                          
                             Homework
{
    
                          
                          
                            //
                          
                          
                             主键,ID
                          
                          
                            public
                          
                          
                            int
                          
                           WorkID { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             作业描述
                          
                          
                            public
                          
                          
                            string
                          
                          ? Description { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             科目(导航属性)
                          
                          
                            public
                          
                           Subject? Subject { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             引用学生对象
                          
                          
                            public
                          
                           Student? Student { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
}


                          
                          
                            public
                          
                          
                            class
                          
                          
                             Subject
{
    
                          
                          
                            //
                          
                          
                             主键:科目ID
                          
                          
                            public
                          
                          
                            int
                          
                           SubID { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
    
                          
                          
                            //
                          
                          
                             科目名称
                          
                          
                            public
                          
                          
                            string
                          
                          ? Name { 
                          
                            get
                          
                          ; 
                          
                            set
                          
                          
                            ; }
}
                          
                        

这次老周加了个实体——Subject,它表示作业的科目(数学、语文等).

导航属性是用于建立实体关系的.

1、学生类中,Homeworks 属性建立与 Homework 对象的关系:一条学生信息可以对应多条作业信息,是一对多的关系; 。

2、作业类中,Subject 属性建立与 Subject 对象的关系。一对一的关系.

在 DbContext 的自定义类型中,三个实体间的关系配置如下:

                          
                            protected
                          
                          
                            override
                          
                          
                            void
                          
                          
                             OnModelCreating(ModelBuilder modelBuilder)
{
    
                          
                          
                            //
                          
                          
                             设置主键
                          
                          
    modelBuilder.Entity<Student>().HasKey(s =>
                          
                             s.StuID);
    modelBuilder.Entity
                          
                          <Homework>().HasKey(w =>
                          
                             w.WorkID);
    modelBuilder.Entity
                          
                          <Subject>().HasKey(u =>
                          
                             u.SubID);
    
                          
                          
                            //
                          
                          
                             建立模型关系
                          
                          
    modelBuilder.Entity<Student>().HasMany(s => s.Homeworks).WithOne(w =>
                          
                             w.Student);
    modelBuilder.Entity
                          
                          <Homework>().HasOne(w =>
                          
                             w.Subject);
}
                          
                        

这是咱们常规的关系配置方法,从当前实体到另一实体的关系描述为 HasXXX 方法;HasXXX 方法调用后,会顺带调用一个 WithXXX 方法。WithXXX 方法是反向描述,即描述另一个实体与当前实体的关系。这样调用可以建立比较完整的相对关系.

在上述代码中,Student -> Homework 是一对多,所以,Student 实体上调用 HasMany 方法;之后是反向关系,Homework -> Student 是一对一关系,也就是说,一条 Homework 记录通过外键只引用一条学生记录。因此调用了 WithOne 方法.

Homework -> Subject 是一对一,所以在 Homework 实体上调用 HasOne 方法。这里,Homework 与 Subject 两实体并没有建立相互引用的关系,仅仅是作业中引用了科目信息,而 Subject 实体自身可以独立,它不需要引用 Homework 的任何实例,因此没有调用 WithXXX 方法.

由于实体之间建立的关系是相对的,即参照当前对象。所以,上面代码也可以这样写:

                          modelBuilder.Entity<Homework>().HasOne(h => h.Student).WithMany(s =>
                          
                             s.Homeworks);
modelBuilder.Entity
                          
                          <Homework>().HasOne(h => h.Subject);
                        

要注意的是, 这两种关系配置其实是相同的,所以两者任选一即可 ,不要重复配置.

两种关系配置的差别就在选择谁来做“当前实体”,即以当前实体为参照而建立相对关系。第二种方法是以 Homework 实体为当前实体,一条作业信息只关联一位学生,所以是一对一,调用 HasOne 方法;反过来,一条学生信息可包含多条作业信息,所以是一对多,即调用 WithMany 方法.

定义几个静态方法,用于验证模型建得对不对.

首先,InitDatabase 方法负责运行阶段创建数据库,并插入一些测试数据.

                          
                            static
                          
                          
                            void
                          
                          
                             InitDatabase()
{
    
                          
                          
                            using
                          
                           MyContext cxt = 
                          
                            new
                          
                          
                            ();
    
                          
                          
                            //
                          
                          
                             确保数据已创建
                          
                          
                            bool
                          
                           v =
                          
                             cxt.Database.EnsureCreated();
    
                          
                          
                            //
                          
                          
                             如果数据库已存在,不用初始化数据
                          
                          
                            if
                          
                           (!
                          
                            v)
        
                          
                          
                            return
                          
                          
                            ;
    
                          
                          
                            /*
                          
                          
                              初始化数据  
                          
                          
                            */
                          
                          
                            //
                          
                          
                             这是科目
                          
                          
    Subject s1 = 
                          
                            new
                          
                          (){ Name = 
                          
                            "
                          
                          
                            语文
                          
                          
                            "
                          
                          
                            };
    Subject s2 
                          
                          = 
                          
                            new
                          
                          (){ Name = 
                          
                            "
                          
                          
                            数学
                          
                          
                            "
                          
                          
                            };
    Subject s3 
                          
                          = 
                          
                            new
                          
                          (){ Name = 
                          
                            "
                          
                          
                            英语
                          
                          
                            "
                          
                          
                            };
    Subject s4 
                          
                          = 
                          
                            new
                          
                          (){ Name = 
                          
                            "
                          
                          
                            物理
                          
                          
                            "
                          
                          
                            };
    Subject s5 
                          
                          = 
                          
                            new
                          
                          (){ Name = 
                          
                            "
                          
                          
                            地理
                          
                          
                            "
                          
                          
                            };
    cxt.Subjects.AddRange(
                          
                          
                            new
                          
                          
                            []{
        s1, s2, s3, s4, s5
    });
    
                          
                          
                            //
                          
                          
                             学生和作业可以一起添加
                          
                          
                                cxt.Students.Add(
        
                          
                          
                            new
                          
                          
                             Student{
            Name 
                          
                          = 
                          
                            "
                          
                          
                            小华
                          
                          
                            "
                          
                          
                            ,
            Grade 
                          
                          = 
                          
                            4
                          
                          
                            ,
            Homeworks 
                          
                          = 
                          
                            new
                          
                          
                             []
            {
                
                          
                          
                            new
                          
                          
                             Homework
                {
                    Description 
                          
                          = 
                          
                            "
                          
                          
                            背单词3500个
                          
                          
                            "
                          
                          
                            ,
                    Subject 
                          
                          =
                          
                             s3
                },
                
                          
                          
                            new
                          
                          
                             Homework
                {
                    Description 
                          
                          = 
                          
                            "
                          
                          
                            作文《我是谁,我在哪里》
                          
                          
                            "
                          
                          
                            ,
                    Subject 
                          
                          =
                          
                             s1
                },
                
                          
                          
                            new
                          
                          
                             Homework
                {
                   Description 
                          
                          = 
                          
                            "
                          
                          
                            手绘广州地铁网络图
                          
                          
                            "
                          
                          
                            ,
                   Subject 
                          
                          =
                          
                             s5
                }
            }
        }
    );
    cxt.Students.Add(
        
                          
                          
                            new
                          
                          
                             Student
        {
            Name 
                          
                          = 
                          
                            "
                          
                          
                            王双喜
                          
                          
                            "
                          
                          
                            ,
            Grade 
                          
                          = 
                          
                            3
                          
                          
                            ,
            Homeworks 
                          
                          = 
                          
                            new
                          
                          
                            [] {
                
                          
                          
                            new
                          
                          
                             Homework
                {
                    Description 
                          
                          = 
                          
                            "
                          
                          
                            完型填空练习
                          
                          
                            "
                          
                          
                            ,
                    Subject 
                          
                          =
                          
                             s3
                }
            }
        }
    );
    cxt.Students.Add(
        
                          
                          
                            new
                          
                          
                             Student
        {
            Name 
                          
                          = 
                          
                            "
                          
                          
                            割麦小王子
                          
                          
                            "
                          
                          
                            ,
            Grade 
                          
                          = 
                          
                            5
                          
                          
                            ,
            Homeworks 
                          
                          = 
                          
                            new
                          
                          
                            []{
                
                          
                          
                            new
                          
                          
                             Homework
                {
                    Description 
                          
                          = 
                          
                            "
                          
                          
                            实验:用激光给蟑螂美容
                          
                          
                            "
                          
                          
                            ,
                    Subject 
                          
                          =
                          
                             s4
                },
                
                          
                          
                            new
                          
                          
                             Homework{
                    Description 
                          
                          = 
                          
                            "
                          
                          
                            翻译文言文《醉驾通鉴》
                          
                          
                            "
                          
                          
                            ,
                    Subject 
                          
                          =
                          
                             s1
                }
            }
        }
    );
    
                          
                          
                            //
                          
                          
                             保存到数据库
                          
                          
                                cxt.
                             SaveChanges 
                            ();
}
                          
                        

SaveChanges 方法记得调用,调用了才会保存数据.

ShowData 方法负责在控制台打印数据.

                          
                            static
                          
                          
                            void
                          
                          
                             ShowData()
{
    
                          
                          
                            using
                          
                           MyContext ctx = 
                          
                            new
                          
                          
                            ();
    
                          
                          
                            var
                          
                           students = ctx.Students.
                          
                            Include
                          
                          (s =>
                          
                             s.Homeworks)
                .
                             ThenInclude 
                            (hw 
                          
                          =>
                          
                             hw.Subject)
                .
                             AsEnumerable 
                            ();
    
                          
                          
                            //
                          
                          
                             打印学生信息
                          
                          
    Console.WriteLine(
                          
                            "
                          
                          
                            {0,-5}{1,-10}{2,-6}
                          
                          
                            "
                          
                          , 
                          
                            "
                          
                          
                            学号
                          
                          
                            "
                          
                          , 
                          
                            "
                          
                          
                            姓名
                          
                          
                            "
                          
                          , 
                          
                            "
                          
                          
                            年级
                          
                          
                            "
                          
                          
                            );
    Console.WriteLine(
                          
                          
                            "
                          
                          
                            ----------------------------------------------------
                          
                          
                            "
                          
                          
                            );
    
                          
                          
                            foreach
                          
                          (
                          
                            var
                          
                           stu 
                          
                            in
                          
                          
                             students)
    {
        Console.WriteLine($
                          
                          
                            "
                          
                          
                            {stu.StuID,-7}{stu.Name,-10}{stu.Grade,-4}
                          
                          
                            "
                          
                          
                            );
        
                          
                          
                            //
                          
                          
                             打印作业信息
                          
                          
                            foreach
                          
                          (Homework wk 
                          
                            in
                          
                          
                             stu.Homeworks)
        {
            Console.Write(
                          
                          
                            "
                          
                          
                            >> {0,-4}
                          
                          
                            "
                          
                          , wk.Subject!
                          
                            .Name);
            Console.WriteLine(wk.Description);
        }
        Console.Write(
                          
                          
                            "
                          
                          
                            \n\n
                          
                          
                            "
                          
                          
                            );
    }
}
                          
                        

在加载数据时得小心,因为如果你只访问 Students 集合,那么,Homeworks 和 Subjects 集合不会加载,这会使得 Student 实体的 Homeworks 属性变为空。为了让访问 Students 集合时同时加载关联的数据,要用 Include 方法.

第一个 Include 方法加载 Homeworks 属性引用的 Homework对象;第二个ThenInclude 方法是指在加载 Homework 后,Homework 实体的 Subject 属性引用了 Subject 对象,所以 ThenInclude 方法是通知模型顺便加载 Subjects 集合.

最后,要调用一下实际触发查询的方法,如 AsEnumerable 方法,这样才会让查询执行,你在内存中才能访问到数据。当然,像 ToArray、ToList 之类的方法也可以,这个和 LINQ 语句的情况类似。要调用到相应的方法才触发查询真正执行.

RemoveDatabase 方法是可选的,删除数据库。咱们这是演示,免得在数据库中存太多不必要的东西。测试完代码可以调用一下它,删除数据库。这里老周照例用 SQL Server LocalDB 来演示.

                          
                            static
                          
                          
                            void
                          
                          
                             RemoveDatabase()
{
    
                          
                          
                            using
                          
                           MyContext c = 
                          
                            new
                          
                          
                            ();
    c.Database.EnsureDeleted();
}
                          
                        

------------------------------------------------------------------------------------------- 。

用的时候,按顺调用这些方法,就可以测试了.

                             Console.WriteLine(
                          
                            "
                          
                          
                            ** 第一步:初始化数据库。【请按任意键继续】
                          
                          
                            "
                          
                          
                            );
   _ 
                          
                          = Console.ReadKey(
                          
                            true
                          
                          
                            );
   InitDatabase();

   Console.WriteLine(
                          
                          
                            "
                          
                          
                            ** 第二步:显示数据。【请按任意键继续】
                          
                          
                            "
                          
                          
                            );
   _ 
                          
                          = Console.ReadKey(
                          
                            true
                          
                          
                            );
   ShowData();

   
                          
                          
                            //
                          
                          
                            Console.WriteLine("** 第三步:删除数据库。【请按任意键继续】");
   
                          
                          
                            //
                          
                          
                            _ = Console.ReadKey();
   
                          
                          
                            //
                          
                          
                            RemoveDatabase();
                          
                        

产生的数据表如下图所示:

  。

我们上面的这个模型还是有点问题的,可以看一下,生成的数据表是没有删除约束的.

                          
                            CREATE
                          
                          
                            TABLE
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Homeworks
                          
                          
                            ]
                          
                          
                             (
    
                          
                          
                            [
                          
                          
                            WorkID
                          
                          
                            ]
                          
                          
                            INT
                          
                          
                            IDENTITY
                          
                           (
                          
                            1
                          
                          , 
                          
                            1
                          
                          ) 
                          
                            NOT
                          
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            [
                          
                          
                            Description
                          
                          
                            ]
                          
                          
                            NVARCHAR
                          
                           (
                          
                            MAX
                          
                          ) 
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            [
                          
                          
                            SubjectSubID
                          
                          
                            ]
                          
                          
                            INT
                          
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            [
                          
                          
                            StudentStuID
                          
                          
                            ]
                          
                          
                            INT
                          
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            PK_Homeworks
                          
                          
                            ]
                          
                          
                            PRIMARY
                          
                          
                            KEY
                          
                          
                            CLUSTERED
                          
                           (
                          
                            [
                          
                          
                            WorkID
                          
                          
                            ]
                          
                          
                            ASC
                          
                          
                            ),
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            FK_Homeworks_Students_StudentStuID
                          
                          
                            ]
                          
                          
                            FOREIGN
                          
                          
                            KEY
                          
                           (
                          
                            [
                          
                          
                            StudentStuID
                          
                          
                            ]
                          
                          ) 
                          
                            REFERENCES
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Students
                          
                          
                            ]
                          
                           (
                          
                            [
                          
                          
                            StuID
                          
                          
                            ]
                          
                          
                            ),
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            FK_Homeworks_Subjects_SubjectSubID
                          
                          
                            ]
                          
                          
                            FOREIGN
                          
                          
                            KEY
                          
                           (
                          
                            [
                          
                          
                            SubjectSubID
                          
                          
                            ]
                          
                          ) 
                          
                            REFERENCES
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Subjects
                          
                          
                            ]
                          
                           (
                          
                            [
                          
                          
                            SubID
                          
                          
                            ]
                          
                          
                            )
);
                          
                        

假如现在我要删掉一条学生记录.

                          
                            using
                          
                          (MyContext dbcontext = 
                          
                            new
                          
                          
                            ())
{
    
                          
                          
                            //
                          
                          
                             删第一条记录
                          
                          
                            var
                          
                           one =
                          
                             dbcontext.Students.FirstOrDefault();
    
                          
                          
                            if
                          
                          (one != 
                          
                            null
                          
                          
                            )
    {
        dbcontext.Students.Remove(one);
        dbcontext.SaveChanges();
    }
}
                          
                        

但删除的时候会遇到错误.

这表明咱们要配置级联删除.

                          
                            public
                          
                          
                            class
                          
                          
                             MyContext : DbContext
{
    
                          
                          
                            public
                          
                           DbSet<Student> Students => Set<Student>
                          
                            ();
    
                          
                          
                            public
                          
                           DbSet<Homework> Homeworks => Set<Homework>
                          
                            ();
    
                          
                          
                            public
                          
                           DbSet<Subject> Subjects => Set<Subject>
                          
                            ();

    
                          
                          
                            protected
                          
                          
                            override
                          
                          
                            void
                          
                          
                             OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseSqlServer(
                          
                          
                            @"
                          
                          
                            server=(localdb)\MSSQLLocalDB;Database=TestDB;Integrated Security=True
                          
                          
                            "
                          
                          
                            );
    }

    
                          
                          
                            protected
                          
                          
                            override
                          
                          
                            void
                          
                          
                             OnModelCreating(ModelBuilder modelBuilder)
    {
        ……
        
                          
                          
                            //
                          
                          
                             建立模型关系
                          
                          
        modelBuilder.Entity<Student>
                          
                            ()
                    .HasMany(s 
                          
                          =>
                          
                             s.Homeworks)
                    .WithOne(w 
                          
                          =>
                          
                             w.Student)
                    
                             .OnDelete(DeleteBehavior.Cascade) 
                            ;
        modelBuilder.Entity
                          
                          <Homework>().HasOne(w =>
                          
                             w.Subject);
    }
}
                          
                        

现在再删一次看看.

可以看到,与第一位学生有关的作业记录也一并被删除了。生成的数据表也与前面有一点差异.

                          
                            CREATE
                          
                          
                            TABLE
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Homeworks
                          
                          
                            ]
                          
                          
                             (
    
                          
                          
                            [
                          
                          
                            WorkID
                          
                          
                            ]
                          
                          
                            INT
                          
                          
                            IDENTITY
                          
                           (
                          
                            1
                          
                          , 
                          
                            1
                          
                          ) 
                          
                            NOT
                          
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            [
                          
                          
                            Description
                          
                          
                            ]
                          
                          
                            NVARCHAR
                          
                           (
                          
                            MAX
                          
                          ) 
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            [
                          
                          
                            SubjectSubID
                          
                          
                            ]
                          
                          
                            INT
                          
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            [
                          
                          
                            StudentStuID
                          
                          
                            ]
                          
                          
                            INT
                          
                          
                            NULL
                          
                          
                            ,
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            PK_Homeworks
                          
                          
                            ]
                          
                          
                            PRIMARY
                          
                          
                            KEY
                          
                          
                            CLUSTERED
                          
                           (
                          
                            [
                          
                          
                            WorkID
                          
                          
                            ]
                          
                          
                            ASC
                          
                          
                            ),
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            FK_Homeworks_Students_StudentStuID
                          
                          
                            ]
                          
                          
                            FOREIGN
                          
                          
                            KEY
                          
                           (
                          
                            [
                          
                          
                            StudentStuID
                          
                          
                            ]
                          
                          ) 
                          
                            REFERENCES
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Students
                          
                          
                            ]
                          
                           (
                          
                            [
                          
                          
                            StuID
                          
                          
                            ]
                          
                          )
                          
                             ON 
                             DELETE 
                             CASCADE 
                          
                          
                            ,
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            FK_Homeworks_Subjects_SubjectSubID
                          
                          
                            ]
                          
                          
                            FOREIGN
                          
                          
                            KEY
                          
                           (
                          
                            [
                          
                          
                            SubjectSubID
                          
                          
                            ]
                          
                          ) 
                          
                            REFERENCES
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Subjects
                          
                          
                            ]
                          
                           (
                          
                            [
                          
                          
                            SubID
                          
                          
                            ]
                          
                          
                            )
);
                          
                        

约束里面显然多了 ON DELETE CASCADE 语句.

回忆一下,在上一篇水文中,咱们使用主从对象后,我们在模型中没有明确配置级联删除,但生成的数据表中自动加上级联删除了.

这是不是说明:主从关系的实体对象里,主实体对从属实体的控制更强烈,咱们再对比对比看.

现在,让 Student 和 Homework 成为主从关系.

                          
                            public
                          
                          
                            class
                          
                          
                             MyContext : DbContext
{
    
                          
                          
                            public
                          
                           DbSet<Student> Students => Set<Student>
                          
                            ();
    
                          
                          
                            public
                          
                           DbSet<Homework> Homeworks => Set<Homework>
                          
                            ();
    
                          
                          
                            public
                          
                           DbSet<Subject> Subjects => Set<Subject>
                          
                            ();

    
                          
                          
                            protected
                          
                          
                            override
                          
                          
                            void
                          
                          
                             OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        ……
    }

    
                          
                          
                            protected
                          
                          
                            override
                          
                          
                            void
                          
                          
                             OnModelCreating(ModelBuilder modelBuilder)
    {
        
                          
                          
                            //
                          
                          
                             设置主键
                          
                          
        modelBuilder.Entity<Student>().HasKey(s =>
                          
                             s.StuID);
        modelBuilder.Entity
                          
                          <Subject>().HasKey(u =>
                          
                             u.SubID);
        
                          
                          
                            //
                          
                          
                             建立模型关系
                          
                          
        modelBuilder.Entity<Student>
                          
                            ()
                    .
                             OwnsMany(s 
                          
                          
                            => s.Homeworks, mrb =>
                          
                          
                             { 
                             mrb.WithOwner(w 
                          
                          
                            =>
                             w.Student); 
                          
                          
                             mrb.HasKey(w 
                            =>
                             w.WorkID); 
                          
                          
                             mrb.HasOne(w 
                            =>
                          
                          
                             w.Subject); 
                          
                          
                             }); 
                            
                    
    }
}
                          
                        

上次我们也证实过,凡成为从属的实体是无法单独进行配置的(如主键等),只能在配置主从关系的时候通过 OwnsMany 方法的委托来配置.

主从关系会自动生成级联删除语句.

                          
                            CREATE
                          
                          
                            TABLE
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Homeworks
                          
                          
                            ]
                          
                          
                             (
    ……,
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            PK_Homeworks
                          
                          
                            ]
                          
                          
                            PRIMARY
                          
                          
                            KEY
                          
                          
                            CLUSTERED
                          
                           (
                          
                            [
                          
                          
                            WorkID
                          
                          
                            ]
                          
                          
                            ASC
                          
                          
                            ),
    
                          
                          
                            CONSTRAINT
                          
                          
                            [
                          
                          
                            FK_Homeworks_Students_StudentStuID
                          
                          
                            ]
                          
                          
                            FOREIGN
                          
                          
                            KEY
                          
                           (
                          
                            [
                          
                          
                            StudentStuID
                          
                          
                            ]
                          
                          ) 
                          
                            REFERENCES
                          
                          
                            [
                          
                          
                            dbo
                          
                          
                            ]
                          
                          .
                          
                            [
                          
                          
                            Students
                          
                          
                            ]
                          
                           (
                          
                            [
                          
                          
                            StuID
                          
                          
                            ]
                          
                          ) 
                          
                             ON 
                             DELETE 
                             CASCADE 
                          
                          
                            ,
    ……
);
                          
                        

还有一点更关键的,Homework 成为 Student 的从对象后,你甚至无法直接访问 Homeworks 集合,必须通过 Sudents 集合来访问.

                          
                            using
                          
                           (MyContext ctx = 
                          
                            new
                          
                          
                             MyContext())
{
    
                          
                          
                            foreach
                          
                          (Homework hw 
                          
                            in
                          
                          
                             ctx.Homeworks)
    {
        Console.WriteLine($
                          
                          
                            "
                          
                          
                            {hw.Description}
                          
                          
                            "
                          
                          
                            );
    }
}
                          
                        

上述代码会抛异常.

这很明了,就是说你必须通过 Student 实体才能访问 Homework。所以,正确的做法要这样:

                          
                            using
                          
                           (MyContext ctx = 
                          
                            new
                          
                          
                             MyContext())
{
    ctx.Subjects.Load();    
                          
                          
                            //
                          
                          
                             这个可不会自动加载,必须Load
                          
                          
                             foreach 
                            (Student stu 
                             in 
                          
                          
                             ctx.Students) 
                            
    {
        Console.WriteLine(
                          
                          
                            "
                          
                          
                            【{0}】同学
                          
                          
                            "
                          
                          
                            , stu.Name);
        
                          
                          
                            foreach
                          
                          (Homework work 
                          
                            in
                          
                          
                             stu.Homeworks 
                            )
        {
            Console.WriteLine(
                          
                          
                            "
                          
                          
                              {0}:{1}
                          
                          
                            "
                          
                          , work.Subject?
                          
                            .Name, work.Description);
        }
    }
}
                          
                        

Subjects 集合为什么要显式地调用 Load 方法呢?因为 Homework 与 Subject 实体并没有建立主从关系,Subject 对象要手动加载.

这样访问就不出错了.

----------------------------------------------------------------------------------- 。

最后,咱们来总结一下:

1、普通关系的数据未自动加载,要显式Load,或者 Include 方法加载。主从关系会自动加载从属数据; 。

2、建立主从关系后,主实体对从实体是完全控制了,不仅自动生成级联删除等约束,而且你还不能直接访问从实体,只能透过主实体访问;普通关系的实体需要手动配置约束.

  。

======================================================== 。

下面是老周讲故事时间.

上大学的时候,在《程序员》杂志上看过一句很“权威”的话:程序员是世上最有尊严的职业,不用酒局饭局,不用看人脸色,想干啥干啥,自由得很。然而,“多年以后一场大雨惊醒沉睡的我,突然之间都市的霓虹都不再闪烁”。客户说需求要这样这样,你改不改?改完之后客户又说还是改回那样那样,你改不改?总奸,哦不,总监说要这样这样,你能那样那样吗?客户说:“我们希望增加XXX功能,最好可以分开YYY、KKK 来管理。这些对你们来很简单的,动动鼠标就好了嘛!” 你动动鼠标试试?

再说了,哪个公司哪个单位的领导不是酒囊饭袋?IT 公司没有吗?哪儿都有,这世界最不缺的就是酒囊饭袋,最缺的是成吉思汗.

所以说,最TM自由、耍得最爽的就写博客,爱写啥写啥,套用土杰伦的歌词就是“你爱看就看,不爱看拉倒”。至于码农,就如同被压迫数千年的农民一样,没本质区别。所以,我们在给后辈讲码农生涯时,千万不要给他们画大饼,充不了饥。我们更应该教会他们程序员的最基本职业道德—— sudo rm -rf /*.

  。

最后此篇关于【EFCore】主从实体关系与常见实体关系的区别的文章就讲到这里了,如果你想了解更多关于【EFCore】主从实体关系与常见实体关系的区别的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com