【極力分享】[C#/.NET]Entity Framework(EF) Code First 多對多關系的實體增,刪,改,查操作全程詳細示例


 【轉載自https://segmentfault.com/a/1190000004152660】

[C#/.NET]Entity Framework(EF) Code First 多對多關系的實體增,刪,改,查操作全程詳細示例

本文我們來學習一下在Entity Framework中使用Context刪除多對多關系的實體是如何來實現的。我們將以一個具體的控制台小實例來了解和學習整個實現Entity Framework 多對多關系的實體刪除的操作過程。

你將學習到

  • 怎樣創建一個引用Entity Framework的項目;

  • 怎樣配置Entity Framework的數據庫連接;

  • 怎樣去掉Entity Framework Code First 生成的表名的復數;

  • 怎樣通過EntityTypeConfiguartion<T>配置實體的Fluent API ;

  • 怎樣配置Entity Framework的實體多對多的關系映射;

  • Entity Framework數據初始化;

  • 怎樣使用包管理工具控制台來生成和更新數據庫;

  • 怎么刪除Entity Framework中的多對多關系的數據。

本示例開發環境

  • 操作系統:Windows 10

  • 開發工具及版本:Visual Studio 2015 Update 1

  • .NET Framework版本:.NET Framework 4.6

  • 程序輸出方式:控制台應用程序

第一步、創建項目並引用程序包

1.1 創建項目

首先,我們創建一個控制台應用程序,取名為:EFRemoveManyToManyDemo,如下圖:

 

1.2 引用程序包

接着打開程序包管理工具,安裝必須的EntityFramework引用包,如下:

 

第二步、創建實體類並配置數據庫連接

2.1 創建實體類

安裝好Entity Framework包之后 ,我們先創建本示例需要的兩個實體對應的類:User和Role(都放在Model的文件夾下),如下:

User.cs

 1 using System;
 2 using System.Collections.Generic;
 3 
 4 namespace EFRemoveManyToManyDemo.Model
 5 {
 6     public class User
 7     {
 8         public User()
 9         {
10             Roles = new HashSet<Role>();
11         }
12         public int Id { get; set; }
13         public string FirstName { get; set; }
14         public string LastName { get; set; }
15         public DateTime? CreatedOn { get; set; }
16         public virtual ICollection<Role> Roles { get; set; }//多對多關系中兩邊都要寫上ICollection
17     }
18 }

 

Role.cs

 1 using System.Collections.Generic;
 2 
 3 namespace EFRemoveManyToManyDemo.Model
 4 {
 5     public class Role
 6     {
 7         public Role()
 8         {
 9             this.Users = new HashSet<User>();!!依賴注入中的構造器注入
10         }
11         public int Id { get; set; }
12         public string Name { get; set; }
13 
14         public virtual ICollection<User> Users { get; set; }
15         //多對多關系中兩邊都要寫上ICollection
16     }
17 }

 

2.2 配置Fluent API

為了配置Fluent API,新建一個Mapping文件夾,再分別創建User的配置文件UserConfigurationMapping和Role的配置文件RoleConfigurationMapping,如下:

UserConfiguration.cs

using EFRemoveManyToManyDemo.Model;
using System.Data.Entity.ModelConfiguration;

namespace EFRemoveManyToManyDemo.Mapping
{
    public class UserConfigurationMapping : EntityTypeConfiguration<User>
    {
        public UserConfigurationMapping()
        {
            Property(x => x.FirstName).HasMaxLength(50).IsRequired();
            Property(x => x.LastName).HasMaxLength(50).IsRequired();
        }
    }
}

 

RoleConfigurationMapping.cs

 1 using EFRemoveManyToManyDemo.Model;
 2 using System.Data.Entity.ModelConfiguration;
 3 
 4 namespace EFRemoveManyToManyDemo.Mapping
 5 {
 6     public class RoleConfigurationMapping : EntityTypeConfiguration<Role>
 7     {
 8         public RoleConfigurationMapping()
 9         {
10             HasKey(x => x.Id);
11             Property(x => x.Name).HasMaxLength(50).IsRequired();
12             HasMany(x => x.Users)
13                 .WithMany(x => x.Roles)
14                 .Map(m =>
15                 {
16                     m.MapLeftKey("RoleId");
17                     m.MapRightKey("UserId");
18                     m.ToTable("LNK_User_Role");
19                 });
20         }
21     }
22 }

 

2.3 創建Context類

接下來,我們再創建一個名為:ManyToManyRemoveContext的類,該類繼承至DbContext類,用於管理數據庫的連接上下文和數據庫初始化等的一些配置和操作,如下:

using EFRemoveManyToManyDemo.Mapping;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;

namespace EFRemoveManyToManyDemo
{
    public class ManyToManyRemoveContext : DbContext
    {
        public ManyToManyRemoveContext() : base("ManyToManyRemoveContext")
        {

        }
    }
}

 

2.4 配置連接字符串

再在App.config配置文件中添加本地的數據庫連接字符串,大致如下(具體的請根據你的實際數據連接參數來):

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
  </configSections>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6" />
  </startup>
  <connectionStrings>
    <add name="ManyToManyRemoveContext" connectionString="server=你的數據庫服務器地址;database=ManyToManyRemoveDemo;uid=你的數據庫登錄名;pwd=密碼" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="mssqllocaldb" />
      </parameters>
    </defaultConnectionFactory>
    <providers>
      <provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
    </providers>
  </entityFramework>
</configuration>

 

2.5 重寫Context

為了將我們剛才寫的Fluent API應用到對應的實體上,所以我們需要重寫(override)DbContext的OnModelCreating方法,如下:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            modelBuilder.Configurations.Add(new UserConfigurationMapping());
            modelBuilder.Configurations.Add(new RoleConfigurationMapping());
        }

 

其中

modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

  是將Entity Framework Code First在實體類生成對應表時去掉表名的復數用的。簡單地說就是,默認情況下,Entity Framework Code First在由實體類生成對應表時的表名是復數形式的,比如本例的User和Role類,如果沒有這句配置,在生成表名的時候將會是Users和Roles這兩個表名,反之,則是User和Role這兩個表名。

好了,下面貼出完整的ManyToManyRemoveContext.cs文件的代碼:

 1 using EFRemoveManyToManyDemo.Mapping;
 2 using EFRemoveManyToManyDemo.Model;
 3 using System.Data.Entity;
 4 using System.Data.Entity.ModelConfiguration.Conventions;
 5 
 6 namespace EFRemoveManyToManyDemo
 7 {
 8     public class ManyToManyRemoveContext : DbContext
 9     {
10         public ManyToManyRemoveContext() : base("ManyToManyRemoveContext")
11         {
12 
13         }
14 
15         protected override void OnModelCreating(DbModelBuilder modelBuilder)
16         {
17             base.OnModelCreating(modelBuilder);
18             modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
19 
20             modelBuilder.Configurations.Add(new UserConfigurationMapping());
21             modelBuilder.Configurations.Add(new RoleConfigurationMapping());
22         }
23 
24         public DbSet<User> Users { get; set; }
25         public DbSet<Role> Roles { get; set; }
26     }
27 }

 

本文寫到這里,關於Entity Framework的引用,實體類的聲明和Fluent API配置以及與數據庫連接等操作都已完成了。接下來我們要做的是利用Entity Framework所實體生成到配置好的數據庫中。

第三步、應用Migration生成數據庫

在接下來的過程中,我們會用到包管理控制台(Package Manager Console)和三個命令:

3.1 Enable-Migrations

命令使用方式如下圖:

 

運行以上命令后,Entity Framework會自動在我們的項目中創建一個名為Migrations的文件夾,同時生成一個Configuartion.cs的配置文件。這時的項目結構大致是這樣的:

 

生成好Configuration.cs的文件我們再作數據的初始化,如下:

namespace EFRemoveManyToManyDemo.Migrations
{
    using Model;
    using System;
    using System.Collections.Generic;
    using System.Data.Entity.Migrations;
    using System.Linq;
    internal sealed class Configuration : DbMigrationsConfiguration<ManyToManyRemoveContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
        }

        protected override void Seed(ManyToManyRemoveContext context)
        {
            var roles = new List<Role> {
                new Role{ Id=1,Name="超級管理員" },
                new Role{ Id=2,Name="管理員" },
                new Role{ Id=3,Name="一般用戶" }
            };

            var users = new List<User> {
                new User {Id=1,FirstName="Kobe",LastName="Bryant",CreatedOn=DateTime.Now,Roles=roles },
                 new User {Id=2,FirstName="Chris",LastName="Paul",CreatedOn=DateTime.Now,Roles=roles.Where(x=>x.Id==2).ToList() },
                 new User {Id=3,FirstName="Jerimy",LastName="Lin",CreatedOn=DateTime.Now,Roles=roles.Take(2).ToList() }
            };
        }
    }
}

 

完成第一個命令和數據初始化配置后,我們進行第二個命令。

3.2 Add-Migration Init -Verbose

執行此命令后,會在Migrations的文件夾中自動生成一個形如:時間戳_Init.cs的數據遷移文件,如本例生成的是201512040507219_Init.cs這樣一個文件名,其中Init是我們指定的本次數據遷移的版本名稱,文件中的內容如下:

 1 namespace EFRemoveManyToManyDemo.Migrations
 2 {
 3     using System;
 4     using System.Data.Entity.Migrations;
 5     
 6     public partial class Init : DbMigration
 7     {
 8         public override void Up()
 9         {
10             CreateTable(
11                 "dbo.Role",
12                 c => new
13                     {
14                         Id = c.Int(nullable: false, identity: true),
15                         Name = c.String(nullable: false, maxLength: 50),
16                     })
17                 .PrimaryKey(t => t.Id);
18             
19             CreateTable(
20                 "dbo.User",
21                 c => new
22                     {
23                         Id = c.Int(nullable: false, identity: true),
24                         FirstName = c.String(nullable: false, maxLength: 50),
25                         LastName = c.String(nullable: false, maxLength: 50),
26                         CreatedOn = c.DateTime(),
27                     })
28                 .PrimaryKey(t => t.Id);
29             
30             CreateTable(
31                 "dbo.LNK_User_Role",
32                 c => new
33                     {
34                         RoleId = c.Int(nullable: false),
35                         UserId = c.Int(nullable: false),
36                     })
37                 .PrimaryKey(t => new { t.RoleId, t.UserId })
38                 .ForeignKey("dbo.Role", t => t.RoleId, cascadeDelete: true)
39                 .ForeignKey("dbo.User", t => t.UserId, cascadeDelete: true)
40                 .Index(t => t.RoleId)
41                 .Index(t => t.UserId);
42             
43         }
44         
45         public override void Down()
46         {
47             DropForeignKey("dbo.LNK_User_Role", "UserId", "dbo.User");
48             DropForeignKey("dbo.LNK_User_Role", "RoleId", "dbo.Role");
49             DropIndex("dbo.LNK_User_Role", new[] { "UserId" });
50             DropIndex("dbo.LNK_User_Role", new[] { "RoleId" });
51             DropTable("dbo.LNK_User_Role");
52             DropTable("dbo.User");
53             DropTable("dbo.Role");
54         }
55     }
56 }

 

我們可以通過這個文件中的內容看到,有Up()和Down()這兩個方法,Up()方法要執行的其實就是本次數據遷移要對數據進行的操作,而Down()方法則是在以后我們如果要退回到此版本應該執行的操作。

經過以上兩個命令,如你迫不及待地要去數據庫管理工具中查看有一個名叫:ManyToManyRemoveDemo的數據庫是否已生成,那么很遺憾地告訴你,還沒有。這時,我們還得執行最后一個命令來生成數據庫和實體對應的表。

3.3 Update-Database -Verbose

執行以上命令,我們這時再打開數據庫管理工具。沒錯ManyToManyRemoveDemo就在那里。再查看表是否成功生成呢,再檢查一下表中是否有我們初始化的數據呢,沒錯,這些都是可以有的。怎么樣,驚喜吧,歡呼吧,我們做到了!!!

 

但還沒完,請先回復平靜,這還只是一個開始。Entity Framework還可以做得更多,我們需要學習的也還有很多,編程的道路從來就不是一步到位的,得有個過程。一步一步往下看吧。

第四步、增、刪、改、查操作

4.1 查詢數據示例

打開我們項目的Program.cs文件。首先,我們來查詢(Query)一下數據庫中的數據,如下:

 1 static void Main(string[] args)
 2         {
 3             Query();
 4             ReadKey();
 5         }
 6 
 7         static void Query()
 8         {
 9             using (var cxt = new ManyToManyRemoveContext())
10             {
11                 var users = cxt.Users.ToList();
12                 users.ForEach(x =>
13                 {
14                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}\n |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
15                 });
16             }
17         }

 

運行結果如圖:

 

4.2 更新數據示例

再來更新一條數據庫中的數據怎么樣,如下:

 1  static void Main(string[] args)
 2         {
 3             Update();
 4             Query();
 5             ReadKey();
 6         }
 7 
 8 static void Query()
 9         {
10             using (var cxt = new ManyToManyRemoveContext())
11             {
12                 var users = cxt.Users.ToList();
13                 users.ForEach(x =>
14                 {
15                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}\n |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
16                 });
17             }
18         }
19 
20 static void Update()
21         {
22             using (var cxt = new ManyToManyRemoveContext())
23             {
24                 var user = cxt.Users.FirstOrDefault(x=>x.Id==3);
25                 user.FirstName = "ShuHao";
26                 cxt.SaveChanges();
27             }
28         }

 

運行結果如我們所料,如圖:

 

4.3 刪除數據示例

Id為3的User的FirstName已經從數據庫更新了。同樣的,我們要完成刪除操作也比較簡,如下:

1  static void Remove()
2         {
3             using (var cxt = new ManyToManyRemoveContext())
4             {
5                 var user = cxt.Users.FirstOrDefault(x=>x.Id==2);
6                 cxt.Users.Remove(user);
7                 cxt.SaveChanges();
8             }
9         }

 

4.4 新增數據示例

就不再貼圖了。最后是添加操作,向User表添加一個用戶並分配一個Id為1的角色,代碼如下:

 1 static void Add()
 2         {
 3             List<Role> roles;
 4             using (var cxt = new ManyToManyRemoveContext())
 5             {
 6                 roles = cxt.Roles.ToList();
 7                 cxt.Users.Add(new User
 8                 {
 9                     Id = 4,
10                     FirstName = "Console",
11                     LastName = "App",
12                     CreatedOn = DateTime.Now,
13                     Roles = roles.Where(x => x.Id == 1).ToList()
14                 });
15             }
16         }

 

4.5 刪除多對多數據的示例

好了,以上是對User(用戶實體)進行簡單的增、刪、改、查的操作,那么我們要實現多對多的刪除操作呢?也就是刪除用戶的同時刪除其對應的角色,實現的代碼如下:

 1 static void RemoveManyToMany()
 2         {
 3             using (var cxt = new ManyToManyRemoveContext())
 4             {
 5                 var user = cxt.Users.FirstOrDefault(x => x.Id == 1);
 6                 var roles = new List<Role>();
 7                 roles.AddRange(user.Roles.Select(x => x));
 8                 foreach (var role in roles)
 9                 {
10                     user.Roles.Remove(role);
11                 }
12                 cxt.Users.Remove(user);
13                 cxt.SaveChanges();
14             }
15         }

 

運行結果如圖:

 

完整示例代碼及下載地址

好了,最后把Program.cs這個測試文件貼上來,供參考:

 1 using EFRemoveManyToManyDemo.Model;
 2 using System;
 3 using System.Collections.Generic;
 4 using System.Linq;
 5 using static System.Console;
 6 
 7 namespace EFRemoveManyToManyDemo
 8 {
 9     public class Program
10     {
11         static void Main(string[] args)
12         {
13             //Update();
14             WriteLine("Before many to many removed");
15             Query();
16             RemoveManyToMany();
17             WriteLine("After many to many removed");
18             Query();
19             ReadKey();
20         }
21 
22         static void Query()
23         {
24             using (var cxt = new ManyToManyRemoveContext())
25             {
26                 var users = cxt.Users.ToList();
27                 users.ForEach(x =>
28                 {
29                     WriteLine("User First Name:{0},Last Name:{1},Create On:{2}\n |__Roles:{3}", x.FirstName, x.LastName, x.CreatedOn, string.Join(",", x.Roles.Select(r => r.Name)));
30                 });
31             }
32         }
33 
34         static void Add()
35         {
36             List<Role> roles;
37             using (var cxt = new ManyToManyRemoveContext())
38             {
39                 roles = cxt.Roles.ToList();
40                 cxt.Users.Add(new User
41                 {
42                     Id = 4,
43                     FirstName = "Console",
44                     LastName = "App",
45                     CreatedOn = DateTime.Now,
46                     Roles = roles.Where(x => x.Id == 1).ToList()
47                 });
48             }
49         }
50 
51         static void Update()
52         {
53             using (var cxt = new ManyToManyRemoveContext())
54             {
55                 var user = cxt.Users.FirstOrDefault(x => x.Id == 3);
56                 user.FirstName = "ShuHao";
57                 cxt.SaveChanges();
58             }
59         }
60 
61         static void Remove()
62         {
63             using (var cxt = new ManyToManyRemoveContext())
64             {
65                 var user = cxt.Users.FirstOrDefault(x => x.Id == 2);
66                 cxt.Users.Remove(user);
67                 cxt.SaveChanges();
68             }
69         }
70 
71         static void RemoveManyToMany()
72         {
73             using (var cxt = new ManyToManyRemoveContext())
74             {
75                 var user = cxt.Users.FirstOrDefault(x => x.Id == 1);
76                 var roles = new List<Role>();
77                 roles.AddRange(user.Roles.Select(x => x));
78                 foreach (var role in roles)
79                 {
80                     user.Roles.Remove(role);
81                 }
82                 cxt.Users.Remove(user);
83                 cxt.SaveChanges();
84             }
85         }
86     }
87 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM