前言
此文章只是為了給新手程序員,和經驗不多的程序員,在學習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); } }
生成數據庫:
數據庫關系圖:
基礎工作建立完畢。
正文:
我們都知道在codefirst 配置多對多關系的時候,會自動給我買生成中間表。
在modelfirst和datafirst的時候都會生成一個中間類:EmployeeOrder.cs
而codefirst不會生成這個類,本文所闡述的就是使用在codefirst中使用ef、lambada表達對其進行增刪改查的多種情況
-
創建一個訂單
-
添加訂單信息、員工信息到數據表中,建立兩則多對多的聯系
-
清空中間表之間的數據,而不影響employee和order表中的數據
-
給中間表添加數據,給兩個已經存在的數據建立中間關系
-
操作中間表,修改兩個表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過程。