zoukankan      html  css  js  c++  java
  • Entity Framework 6 Recipes 2nd Edition(12-5)译 -> 自动删除相关联实体

    12-5. 自动删除相关联实体

    问题

    当一个实体被删除时,你想自动删除它相关联的实体

    解决方案

    假设你有一个表结构由一个course (科目), course 的classes (课程),以及enrollment (登记学生选课),如 Figure 12-5所示:.

    Figure 12-5. The Course, Class, and Enrollment tables in our database

     

    由上述表生成一个模型,如下图Figure 12-6所示:.

     

    Figure 12-6. A model with the Course, Class, and Enrollment entities and their associations

    当一个course从数据库里被删除,你想把所有的相关classes也被删除,而且与这些classes相关的enrollments也被删除.为了实现这个目标,我们在数据库管理器中为这个关联设置一个级联删除,在数据库管理器中,选择该关联,在属性窗口的”INSERT 和UPDATE规范”下面选择级联删除.

    当这些表导入到模型后,这个级联删除规则也会被导入,你可以

    选择Course 和Class之间的一对多关系中然后在属性窗口里看到这个级联删除规则,如Figure 12-7 所示.

     Figure 12-7. The cascade delete rule from the database was imported into the model, and it is shown in the properties for the association

     

    如Figure 12-7所示的级联删除规则是在概念层的.在存储层也有一个类型的规则. 当一个对象被删除,EF规则及数据库里的级联删除规则,这二者是有必要使object context 和数据库保持同步.

    Listing 12-5 代码演示了级联删除

    Listing 12-5. Using the Underlying Cascade Delete Rules to Delete the Related Objects

        class Program

        {

            static void Main(string[] args)

            {

                RunExample();

            }

            static void RunExample()

            {

                using (var context = new EFRecipesEntities())

                {

                    var course1 = new Course { CourseName = "CS 301" };

                    var course2 = new Course { CourseName = "Math 455" };

                    var en1 = new Enrollment { Student = "James Folk" };

                    var en2 = new Enrollment { Student = "Scott Shores" };

                    var en3 = new Enrollment { Student = "Jill Glass" };

                    var en4 = new Enrollment { Student = "Robin Rosen" };

                    var class1 = new Class { Instructor = "Bill Meyers" };

                    var class2 = new Class { Instructor = "Norma Hall" };

                    class1.Course = course1;

                    class2.Course = course2;

                    class1.Enrollments.Add(en1);

                    class1.Enrollments.Add(en2);

                    class2.Enrollments.Add(en3);

                    class2.Enrollments.Add(en4);

                    context.Classes.Add(class1);

                    context.Classes.Add(class2);

                    context.SaveChanges();

                    context.Classes.Remove(class1);

                    context.SaveChanges();

                }

                using (var context = new EFRecipesEntities())

                {

                    foreach (var course in context.Courses)

                    {

                        Console.WriteLine("Course: {0}", course.CourseName);

                        foreach (var c in course.Classes)

                        {

                            Console.WriteLine(" Class: {0}, Instructor: {1}",

                            c.ClassId.ToString(), c.Instructor);

                            foreach (var en in c.Enrollments)

                            {

                                Console.WriteLine(" Student: {0}", en.Student);

                            }

                        }

                    }

                }

                Console.WriteLine("Press any key to close...");

                Console.ReadLine();

            }

    }

    上述Listing 12-5代码输出结果如下:

    Course: CS 301

    Course: Math 455

    Class: 8, Instructor: Norma Hall

    Student: Jill Glass

    Student: Robin Rosen

    原理

    本小节里数据库与模型都定义了级联删除规则.在模型里,以确保object context与数据库同步.这个规则同时出现在概念层与存储层.

    最佳实践

    那么现在你可能会问:”为什么我们需要在数据库里与模型都定义这条规则?不能只在模型或是数据库里定义吗?”,级联删除存在于概念层来保持object context加载的对象是与数据库的级联删除后的结果是同步的.例如,如果我们已经在object context里为一个科目加载了相关的课程以及学生选课信息,然后我们把这个科目标志为删除,EF同样会把该科目的课程以及学生选课信息标志为删除.在把删除提交到数据库以前,在模型层,级联删除意味着只是把相关联的实体标志为删除,最终,EF才会把实体删除.那么既然EF会删除实体,那么为什么不能只在模型中定义级联删除呢?原因是: EF为了给实体标志为删除, DbContext 必须先加载这些实体,想象一下,如果我们的科目已被加载,但是相关的课程以学生选课信息未被加载,我们删除了科目,那么相关的课程及学生选课信息,由于未被DbContext 加载,所以EF无法将相关的实体标志为删除,也就无法向数据库发送删除相关记录的命令. 然而,如果我们在数据库里定义了级联删除,那么数据库自己就会很好的完成级联删除工作.

    这里的最佳实践就是:在模型与数据库里同时定义级联删除规则.

    如果你在一个模型里添加了一个级联删除规则,那么EF不会覆盖这条规则,即使你从数据库更新模型.

    不幸的是,如果你没有在模型里添加级联删除规则,然后你从数据库更新实体,EF也不会向概念层添加在数据库里新添加的级联删除规则,你将不得不手动添加它.

     

    附:创建示例用到的数据库的脚本文件

     

  • 相关阅读:
    ajax post 时 form数据serialize()
    dapper 自定义数据库字段和代码中Model字段不一致时候的mapping方法
    TImage 的一些操作
    AOP
    SSL、数字签名、CA 工作原理
    RESTFUL
    tomcat
    Hibernate
    设计模式
    Spring配置
  • 原文地址:https://www.cnblogs.com/kid1412/p/5161890.html
Copyright © 2011-2022 走看看