zoukankan      html  css  js  c++  java
  • EF Codefirst 多对多关系 操作中间表的 增删改查(CRUD)

    前言

    此文章只是为了给新手程序员,和经验不多的程序员,在学习ef和lambada表达式的过程中可能遇到的问题。

    本次使用订单表和员工表建立多对多关系。

    首先是订单表:

    复制代码
    public class Order
        {
            public int OrderId { get; set; }
    
            public string OrderTitle { get; set; }
    
            public string CustomerName { get; set; }
    
            public DateTime TransactionDate { get; set; }
    
            [ConcurrencyCheck]
            [Timestamp]
            public byte[] TimeStamp { get; set; }
    
           public virtual ICollection<Employee> InvolvedEmployees { get; set; } 
        }
    复制代码

    接下来是员工表:

    复制代码
    public class Employee
        {
            public int EmployeeId { get; set; }
           
            public string EmployeeName { get; set; }
    
            public virtual ICollection<Order> Orders { get; set; } 
        }
    复制代码

    映射文件(mapping):

    复制代码
    public class OrderMap:EntityTypeConfiguration<Order>
        {
            public OrderMap()
            {
                this.HasKey(o => o.OrderId);
                //OrderId为自增长
                this.Property(o => o.OrderId).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
                this.Property(o => o.OrderTitle).IsRequired().HasMaxLength(64);//订单名称为必填,最大长度为64;
                this.Property(o => o.CustomerName).IsRequired().HasMaxLength(64);//订单名称为必填,最大长度为64;
                this.Property(o => o.TransactionDate).IsRequired(); //订单名称为必填,最大长度为64;
            }
        }
    复制代码
    复制代码
    public class EmployeeMap:EntityTypeConfiguration<Employee>
        {
            /// <summary>
            /// 构造函数
            /// </summary>
            public EmployeeMap()
            {
                this.HasKey(x => x.EmployeeId);
                this.ToTable("Employees");
                this.Property(x => x.EmployeeName).IsRequired().HasMaxLength(20);
    
    
                //设置多对多的关系 .Map()配置用于存储关系的外键列和表。
                /*
                 Employees  HasMany此实体类型配置一对多关系。对应Orders实体               
                WithMany   将关系配置为 many:many,且在关系的另一端有导航属性。
                 * MapLeftKey 配置左外键的列名。左外键指向在 HasMany 调用中指定的导航属性的父实体。
                 * MapRightKey 配置右外键的列名。右外键指向在 WithMany 调用中指定的导航属性的父实体。
                 */
                this.HasMany(x => x.Orders).
                    WithMany(x => x.InvolvedEmployees).
                    Map(m => m.ToTable("EmployeeOrder").
                        MapLeftKey("EmployeeId").
                        MapRightKey("OrderId"));
            }
        }
    复制代码

    dbcontext文件:

    复制代码
    public class EfCodeFirstWithManyDbContext:DbContext
    
        {
            public EfCodeFirstWithManyDbContext()
                : base("DefaultConnection")
            {
                
            }
    
            public IDbSet<Order> Orderses { get; set; }
          public IDbSet<Employee> Employeees { get; set; }
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                modelBuilder.Configurations.Add(new OrderMap());
                modelBuilder.Configurations.Add(new EmployeeMap());
              base.OnModelCreating(modelBuilder);
            }
        }
    复制代码

    生成数据库:

    image

    数据库关系图:

    image

    基础工作建立完毕。

     

    正文:

    我们都知道在codefirst 配置多对多关系的时候,会自动给我买生成中间表。

    在modelfirst和datafirst的时候都会生成一个中间类:EmployeeOrder.cs

    而codefirst不会生成这个类,本文所阐述的就是使用在codefirst中使用ef、lambada表达对其进行增删改查的多种情况

    1. 创建一个订单

    2. 添加订单信息、员工信息到数据表中,建立两则多对多的联系

    3. 清空中间表之间的数据,而不影响employee和order表中的数据

    4. 给中间表添加数据,给两个已经存在的数据建立中间关系

    5. 操作中间表,修改两个表employee和order中值,并且删除中间表中多余的值

    本文大概操作次5种情况。

    代码:

    复制代码
    //添加订单信息、员工信息到数据表中,建立两则多对多的联系
            public static void CreateFullOrderByEmployee()
            {
                #region 添加订单信息、员工信息到数据表中,建立两则多对多的联系
    
                using (var dbContext = new EfCodeFirstWithManyDbContext())
                {
                    var order = new Order
                    {
                        OrderTitle = "购买汽车",
                        CustomerName = "梁桐铭",
                        TransactionDate = DateTime.Now,
                        InvolvedEmployees = new List<Employee>()
                    };
                    var employee1 = new Employee {EmployeeName = "管理员-yoyocms", Orders = new List<Order>()};
                    var employee2 = new Employee {EmployeeName = "主管-yoyocms", Orders = new List<Order>()};
                    //先保存订单到数据库中
                    dbContext.Orderses.Add(order);
    
                    order.InvolvedEmployees.Add(employee1);
                    //order.InvolvedEmployees.Add(employee2);
    
                    // employee2.Orders.Add(order);
                    var res = dbContext.SaveChanges();
                }
    
                #endregion
            }
    复制代码

    为了测试方便对这个方法for循环了20次:

    复制代码
    private static void Main(string[] args)
            {
              
    
                for (int i = 0; i < 20; i++)
                {
                    CreateFullOrderByEmployee();
                }                   
    
                Console.WriteLine("加载完毕,请点击任意键退出");
                Console.ReadKey();
            }
    复制代码

    清空中间表信息,而不影响order表和employee表的信息

    复制代码
    //清空两个中间表之间的关系
            public static void EmptyEmployeeOrder()
            {
                using (var dbContext = new EfCodeFirstWithManyDbContext())
                {
                    //获取到employeeId为20下,所有Orders订单列表信息和员工信息。
                    var employeeToUpdate =
                        dbContext.Employeees.Include(x => x.Orders).FirstOrDefault(x => x.EmployeeId == 20);
                    if (employeeToUpdate != null)
                    {
                        employeeToUpdate.Orders = new List<Order>();
                        dbContext.SaveChanges();
                    }
                    else
                    {
                        Console.WriteLine("查询失败EmptyEmployeeOrder为空");
                    }
                }
            }
    复制代码

    建立员工表和对应的订单表中建立两个表之间的联系

    复制代码
    //建立两个已经存在的数据建立中间关系
            public static void AddInfoEmployeeOrder()
            {
                using (var dbContext = new EfCodeFirstWithManyDbContext())
                {
                    //获取到employeeId为20下,所有Orders订单列表信息和员工信息。
                    var employeeToAdd = dbContext.Employeees.Include(x => x.Orders).FirstOrDefault(x => x.EmployeeId == 20);
                    //设计订单表的集合,将新增的数据填充进来
                    int[] orderIdList = {13, 14, 15, 16, 17, 18, 19};
                    //判断employeeToAdd.Orders中是否有重复的OrderId
                    if (employeeToAdd != null)
                    {
                        //查询出目前员工对应的订单表
                        var employeeOrder = new HashSet<int>(employeeToAdd.Orders.Select(e => e.OrderId));
    
                        foreach (var order in dbContext.Orderses)
                        {
                            //即将要添加orderIdList值的是否包含订单表的id
                            //筛选出orderidList和orders中共同的值,添加到order.OrderId
                            if (orderIdList.Contains(order.OrderId))
                            {
                                //查询出目前employee表中的orderId是否包含了orderIdList中的id
                                if (employeeOrder.Contains(order.OrderId))
                                {
                                    //打印出重复的orderId
                                    Console.WriteLine("重复的ID为" + order.OrderId);
                                    Console.WriteLine("不执行添加结果");
                                }
                                else
                                {
                                    //打印出Employee表中没有orderId
                                    Console.WriteLine("即将添加的值" + order.OrderId);
                                    //添加重复的值
                                    employeeToAdd.Orders.Add(order);
                                }
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("employeeToAdd信息为空");
                    }
    
                    dbContext.SaveChanges();
                }
            }
    复制代码

        修改两个表employee和order中值,并且删除多余的值

    复制代码
    /// <summary>
            ///     修改两个表employee和order中值,并且删除多余的值
            /// </summary>
            public static void UpdateInfoEmployeeOrder()
            {
                //首先获取到EmployeeId=20中,所有的Orders列表和employee信息
                using (var dbContext = new EfCodeFirstWithManyDbContext())
                {
                    var employeeUpdate =
                        dbContext.Employeees.Include(x => x.Orders).FirstOrDefault(x => x.EmployeeId == 20);
                    //需要更改对应的OrderId列表
                    int[] orderIdList = {13, 14, 15, 16, 17, 18, 19};
    
    
                    if (employeeUpdate != null)
                    {
                        //获取employee中的OrderIdlist
                        var employeeOrderIdList = new HashSet<int>(employeeUpdate.Orders.Select(e => e.OrderId));
                        foreach (var order in dbContext.Orderses)
                        {
                            //判断要修改的Orderid和Orders表中的均包含
                            if (orderIdList.Contains(order.OrderId))
                            {
                                if (!employeeOrderIdList.Contains(order.OrderId))
                                {
                                    Console.WriteLine("修改对应的订单Id表" + order.OrderId);
                                    employeeUpdate.Orders.Add(order);
                                }
                            }
                            else
                            {
                                if (employeeOrderIdList.Contains(order.OrderId))
                                {
                                    Console.WriteLine("删除无用的订单表id"+order.OrderId);
                                    employeeUpdate.Orders.Remove(order);
                                }
                            }
                        }
                    }
                    else
                    {
                        Console.WriteLine("查无employeeUpdate 的信息");
                    }
    
                    dbContext.SaveChanges();
                }
            }
    复制代码

     

    尾声

    至此操作实现了对codefirst中,对中间表的CRUD过程。

    源代码下载

  • 相关阅读:
    软工作业02
    进行代码复审训练
    源代码管理工具调查
    软工作业PSP与单元测试训练【任务一】
    15软工 15100340
    进行代码复审训练
    源代码管理工具调查
    软工作业PSP与单元测试训练
    软工课后作业001
    20180320作业2:进行代码复审训练
  • 原文地址:https://www.cnblogs.com/Alex80/p/7791822.html
Copyright © 2011-2022 走看看