zoukankan      html  css  js  c++  java
  • EF基础知识小记五(一对多、多对多处理)

    本文主要讲EF一对多关系和多对多关系的建立

    一、模型设计器

    1、一对多关系

    右键设计器新增关联

    导航属性和外键属性可修改

    2、多对多关系

    右键设计器新增关联

    模型设计完毕之后,根据右键设计器根据模型生成数据库,就能生成对应的表之间的一对多和多对多关联

    二、代码层面

    建表语句如下:

    --建表脚本
    create table Student
    (
        Id int not null,
        Name varchar(30) not null,
        Age int not null
    )
    create table Teacher
    (
        Id int not null,
        Name varchar(30) not null,
        Age int not null
    )
    
    create table StudentTeacher
    (
        StudentId int not null,
        TeacherId int not null
    )
    
    create table InfoCard
    (
        Id int not null,
        [Money] int not null,
        StudentId int not null
    )

    添加常规主键约束,代码如下:

    --单主键约束
    alter table Student add constraint [PK_People]
    primary key clustered (Id Asc)
    
    alter table InfoCard add constraint [PK_InfoCard]
    primary key clustered (Id Asc)
    
    alter table Teacher add constraint [PK_Teacher]
    primary key clustered (Id Asc)

    1、一对多(通过外键)

    --但外键约束(一对多)
    alter table InfoCard add constraint [FK_InfoCard_Student]
    foreign key (StudentId) references Student (Id) on delete no action on update no action

    2、多对多(中间表双主键双外键)

    --双主键约束(多对多)
    alter table StudentTeacher add constraint [PK_StudentTeacher]
    primary key clustered (StudentId,TeacherId Asc)
    
    --双外键约束(多对多)
    alter table StudentTeacher
    add constraint [FK_StudentTeacher_Student]
    foreign key (StudentId) references Student (Id) on delete no action on update no action --级联更新级联删除
    
    alter table StudentTeacher add constraint [FK_StudentTeacher_Teacher]
    foreign key (TeacherId) references Teacher (Id) on delete no action on update no action 

    生成对应的一对多和多对多关联的表之后,根据数据库生成模型就能生成对应的模型

    三、多对多无载荷

    根据上面的建表语言,我们能得出Teacher表和Student表在数据库中的关系如下图:

    数据库关系图:

    在模型设计器中的关系如下图:

    模型设计图:

    观察二图的区别,发现数据库表关系图中的StudentTeacher(链接表)没有出现在模型设计器中。原因如下:

    因为链接表没有标量属性(没有载荷),实体框架认为它存在的唯一价值就是联结Teacher和Student,没有标量属性的联结表,在各自的实体中将以ICollection集合的形式出现.

    当然如果链接表有标量属性,那么模型设计器就会创建一个完成的类来表示链接表。

    四、多对多无载荷增改

                // 添加demo
                using (var context = new EF6RecipeEntities())
                {
                    //给一个Teacher添加几个Student
                    var teacher1 = new Teacher
                    {
                        Id=1,
                        Name = "张老师",
                        Age = 30
                    };
                    var stu1 = new Student
                    {
                        Id = 2,
                        Name = "张三",
                        Age = 20
                    };
                    var stu2 = new Student
                    {
                        Id = 3,
                        Name = "李四",
                        Age = 21
                    };
                    context.Teacher.Add(teacher1);//添加老师teacher1
                    teacher1.Student.Add(stu1);//给老师添加学生stu1
                    teacher1.Student.Add(stu2);//给老师添加学生stu2
    
    
                    //给一个Student添加几个Teacher
                    var stu3 = new Student
                    {
                        Id = 4,
                        Name = "小超",
                        Age = 23
                    };
                    var t2 = new Teacher
                    {
                        Id = 5,
                        Name = "王老师",
                        Age = 33
                    };
                    var t3 = new Teacher
                    {
                        Id = 6,
                        Name = "赵老师",
                        Age = 36
                    };
                    context.Student.Add(stu3);
                    stu3.Teacher.Add(t2);
                    stu3.Teacher.Add(t3);
                    context.SaveChanges();
                }
    
    
                //遍历所有老师下面的所有学生
                using (var context = new EF6RecipeEntities())
                {
                    DbSet<Teacher> ts = context.Teacher;
                    foreach (var t in ts)
                    {
                        Console.WriteLine("姓名:{0},年龄:{1},职位:{2},其管理的学生如下:", t.Name, t.Age, "老师");
                        var stus = t.Student;
                        foreach (var s in stus)
                        {
                            Console.WriteLine("姓名:{0},年龄:{1},职位:{2}", s.Name, s.Age, "学生");
                        }
                        Console.WriteLine();
                    }
                }
                Console.ReadKey();

    五、多对多有载荷

    上面学生和老师的例子并不能很好的说明多对多有载荷的问题,所以换成订单和产品,所以链接表将会产生一个订单数量的载荷(也就是链接表多了一个标量属性),

    模型设计图如下:

    有载荷的多对多关系比无载荷的多对多关系更加的简介明了。因为实体框架不支持在关联上附加载荷,所以有载荷的联结将会生成一个新的实体.

    因为这个附加的载荷,Order需要通过OrderItem来获取与其关联的Product的项.

    六、多对多有载荷增查

                //添加
                using (var context = new EF6RecipeEntities())
                {
                    var product = new Product
                    {
                        Id = 1,
                        Desc = "面包",
                        Price = 10
                    };
                    var order = new Order
                    {
                        Id = 10,
                        OrderDate = DateTime.Now
                    };
                    var orderItem1 = new OrderItem
                    {
                        Order = order,
                        Product = product,
                        Count = 1
                    };
                    product = new Product
                    {
                        Id = 2,
                        Desc = "牛奶",
                        Price = 11
                    };
                    var orderItem2 = new OrderItem
                    {
                        Order = order,
                        Product = product,
                        Count = 2
                    };
                    product = new Product
                    { 
                        Id = 3,
                        Desc = "牛奶面包",
                        Price = 11
                    };
                    var orderItem3 = new OrderItem
                    {
                        Order = order,
                        Product = product,
                        Count = 1
                    };
                    context.OrderItems.Add(orderItem1);
                    context.OrderItems.Add(orderItem2);
                    context.OrderItems.Add(orderItem3);
                    context.SaveChanges();
                }
    
                //遍历
                using (var context = new EF6RecipeEntities())
                {
                    foreach (var order in context.Orders)
                    {
                        Console.WriteLine("订单编号:{0},下单日期:{1},订单详情如下:",order.Id,order.OrderDate.ToShortDateString());
                        foreach (var oi in order.OrderItem)
                        {
                            Console.WriteLine("产品Id:{0},产品描述:{1},产品数量:{2},产品价格:{3}", oi.Product.Id,oi.Product.Desc,oi.Count,oi.Product.Price);
                        }
                        Console.WriteLine();
                    }
                }
                Console.ReadKey();

     七、关于使用多对多有载荷还是多对多无载荷的意见

    如果你有一个无载荷的多对多关系时,你可以考虑通过增加一标识列将其改变为有载荷的多对多关系。当你导入表到你的模型时,你将得到两个包含一对多关系的实体,这意味着,你的代码为将来有可能出现的多载荷做好了准备。增加一整型标识列的代价通常很小,但给模型带来了更大的灵活性。

  • 相关阅读:
    IOS开发笔记 (3)objective c 自己编写测试示例
    IOS开发笔记(六)对iOS多视图开发的初步了解
    (一) MySQL的初步接触!
    Java MD5加密
    JavaSrcipt报错时,说对象不支持此方法,XXX is not a function的情况
    ibatis有关模糊查询和And与Or联查的例子
    (二) 插入数据Insert
    JavaScript的学习(一)
    朋友,请不要焦虑 [转][收藏]
    20080410
  • 原文地址:https://www.cnblogs.com/GreenLeaves/p/7647178.html
Copyright © 2011-2022 走看看