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过程。

    源代码下载

    为了方便和大家交流我建立了几个群,欢迎大家加群交流哦~


    作者:梁桐铭52ABP:基于DDD强大稳定的WEB应用框架!
    出处:http://www.cnblogs.com/wer-ltm
    作品角落的白板报 创作,采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
    欢迎转载,但任何转载必须保留完整文章,在显要地方显示署名以及原文链接。如您有任何疑问或者授权方面的协商,请 加群沟通留言

  • 相关阅读:
    AJAX异步传输——以php文件传输为例
    js控制json生成菜单——自制菜单(一)
    vs2010中关于HTML控件与服务器控件分别和js函数混合使用的问题
    SQL数据库连接到服务器出错——无法连接到XXX
    PHP错误:Namespace declaration statement has to be the very first statement in the script
    【LeetCode】19. Remove Nth Node From End of List
    【LeetCode】14. Longest Common Prefix
    【LeetCode】38. Count and Say
    【LeetCode】242. Valid Anagram
    【LeetCode】387. First Unique Character in a String
  • 原文地址:https://www.cnblogs.com/wer-ltm/p/4944745.html
Copyright © 2011-2022 走看看