本文咱们来学习一下在Entity Framework中使用Context删除多对多关系的实体是如何来实现的。咱们将以一个具体的控制台小实例来了解和学习整个实现Entity Framework 多对多关系的实体删除的操做过程。sql
怎样建立一个引用Entity Framework的项目;数据库
怎样配置Entity Framework的数据库链接;编程
怎样去掉Entity Framework Code First 生成的表名的复数;服务器
怎样经过EntityTypeConfiguartion<T>配置实体的Fluent API ;app
怎样配置Entity Framework的实体多对多的关系映射;ide
Entity Framework数据初始化;工具
怎样使用包管理工具控制台来生成和更新数据库;学习
怎么删除Entity Framework中的多对多关系的数据。开发工具
操做系统:Windows 10测试
开发工具及版本:Visual Studio 2015 Update 1
.NET Framework版本:.NET Framework 4.6
程序输出方式:控制台应用程序
首先,咱们建立一个控制台应用程序,取名为:EFRemoveManyToManyDemo,以下图:
接着打开程序包管理工具,安装必须的EntityFramework引用包,以下:
安装好Entity Framework包以后 ,咱们先建立本示例须要的两个实体对应的类:User和Role(都放在Model的文件夹下),以下:
User.cs
using System; using System.Collections.Generic; namespace EFRemoveManyToManyDemo.Model { public class User { public User() { Roles = new HashSet<Role>(); } public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public DateTime? CreatedOn { get; set; } public virtual ICollection<Role> Roles { get; set; } } }
Role.cs
using System.Collections.Generic; namespace EFRemoveManyToManyDemo.Model { public class Role { public Role() { this.Users = new HashSet<User>(); } public int Id { get; set; } public string Name { get; set; } public virtual ICollection<User> Users { get; set; } } }
为了配置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
using EFRemoveManyToManyDemo.Model; using System.Data.Entity.ModelConfiguration; namespace EFRemoveManyToManyDemo.Mapping { public class RoleConfigurationMapping : EntityTypeConfiguration<Role> { public RoleConfigurationMapping() { HasKey(x => x.Id); Property(x => x.Name).HasMaxLength(50).IsRequired(); HasMany(x => x.Users) .WithMany(x => x.Roles) .Map(m => { m.MapLeftKey("RoleId"); m.MapRightKey("UserId"); m.ToTable("LNK_User_Role"); }); } } }
接下来,咱们再建立一个名为: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") { } } }
再在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>
为了将咱们刚才写的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文件的代码:
using EFRemoveManyToManyDemo.Mapping; using EFRemoveManyToManyDemo.Model; using System.Data.Entity; using System.Data.Entity.ModelConfiguration.Conventions; namespace EFRemoveManyToManyDemo { public class ManyToManyRemoveContext : DbContext { public ManyToManyRemoveContext() : base("ManyToManyRemoveContext") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); modelBuilder.Configurations.Add(new UserConfigurationMapping()); modelBuilder.Configurations.Add(new RoleConfigurationMapping()); } public DbSet<User> Users { get; set; } public DbSet<Role> Roles { get; set; } } }
本文写到这里,关于Entity Framework的引用,实体类的声明和Fluent API配置以及与数据库链接等操做都已完成了。接下来咱们要作的是利用Entity Framework所实体生成到配置好的数据库中。
在接下来的过程当中,咱们会用到包管理控制台(Package Manager Console)和三个命令:
命令使用方式以下图:
运行以上命令后,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() } }; } } }
完成第一个命令和数据初始化配置后,咱们进行第二个命令。
执行此命令后,会在Migrations的文件夹中自动生成一个形如:时间戳_Init.cs的数据迁移文件,如本例生成的是201512040507219_Init.cs这样一个文件名,其中Init是咱们指定的本次数据迁移的版本名称,文件中的内容以下:
namespace EFRemoveManyToManyDemo.Migrations { using System; using System.Data.Entity.Migrations; public partial class Init : DbMigration { public override void Up() { CreateTable( "dbo.Role", c => new { Id = c.Int(nullable: false, identity: true), Name = c.String(nullable: false, maxLength: 50), }) .PrimaryKey(t => t.Id); CreateTable( "dbo.User", c => new { Id = c.Int(nullable: false, identity: true), FirstName = c.String(nullable: false, maxLength: 50), LastName = c.String(nullable: false, maxLength: 50), CreatedOn = c.DateTime(), }) .PrimaryKey(t => t.Id); CreateTable( "dbo.LNK_User_Role", c => new { RoleId = c.Int(nullable: false), UserId = c.Int(nullable: false), }) .PrimaryKey(t => new { t.RoleId, t.UserId }) .ForeignKey("dbo.Role", t => t.RoleId, cascadeDelete: true) .ForeignKey("dbo.User", t => t.UserId, cascadeDelete: true) .Index(t => t.RoleId) .Index(t => t.UserId); } public override void Down() { DropForeignKey("dbo.LNK_User_Role", "UserId", "dbo.User"); DropForeignKey("dbo.LNK_User_Role", "RoleId", "dbo.Role"); DropIndex("dbo.LNK_User_Role", new[] { "UserId" }); DropIndex("dbo.LNK_User_Role", new[] { "RoleId" }); DropTable("dbo.LNK_User_Role"); DropTable("dbo.User"); DropTable("dbo.Role"); } } }
咱们能够经过这个文件中的内容看到,有Up()和Down()这两个方法,Up()方法要执行的其实就是本次数据迁移要对数据进行的操做,而Down()方法则是在之后咱们若是要退回到此版本应该执行的操做。
通过以上两个命令,如你火烧眉毛地要去数据库管理工具中查看有一个名叫:ManyToManyRemoveDemo的数据库是否已生成,那么很遗憾地告诉你,尚未。这时,咱们还得执行最后一个命令来生成数据库和实体对应的表。
执行以上命令,咱们这时再打开数据库管理工具。没错ManyToManyRemoveDemo就在那里。再查看表是否成功生成呢,再检查一下表中是否有咱们初始化的数据呢,没错,这些都是能够有的。怎么样,惊喜吧,欢呼吧,咱们作到了!!!
但还没完,请先回复平静,这还只是一个开始。Entity Framework还能够作得更多,咱们须要学习的也还有不少,编程的道路历来就不是一步到位的,得有个过程。一步一步往下看吧。
打开咱们项目的Program.cs文件。首先,咱们来查询(Query)一下数据库中的数据,以下:
static void Main(string[] args) { Query(); ReadKey(); } static void Query() { using (var cxt = new ManyToManyRemoveContext()) { var users = cxt.Users.ToList(); users.ForEach(x => { 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))); }); } }
运行结果如图:
再来更新一条数据库中的数据怎么样,以下:
static void Main(string[] args) { Update(); Query(); ReadKey(); } static void Query() { using (var cxt = new ManyToManyRemoveContext()) { var users = cxt.Users.ToList(); users.ForEach(x => { 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))); }); } } static void Update() { using (var cxt = new ManyToManyRemoveContext()) { var user = cxt.Users.FirstOrDefault(x=>x.Id==3); user.FirstName = "ShuHao"; cxt.SaveChanges(); } }
运行结果如咱们所料,如图:
Id为3的User的FirstName已经从数据库更新了。一样的,咱们要完成删除操做也比较简,以下:
static void Remove() { using (var cxt = new ManyToManyRemoveContext()) { var user = cxt.Users.FirstOrDefault(x=>x.Id==2); cxt.Users.Remove(user); cxt.SaveChanges(); } }
就再也不贴图了。最后是添加操做,向User表添加一个用户并分配一个Id为1的角色,代码以下:
static void Add() { List<Role> roles; using (var cxt = new ManyToManyRemoveContext()) { roles = cxt.Roles.ToList(); cxt.Users.Add(new User { Id = 4, FirstName = "Console", LastName = "App", CreatedOn = DateTime.Now, Roles = roles.Where(x => x.Id == 1).ToList() }); } }
好了,以上是对User(用户实体)进行简单的增、删、改、查的操做,那么咱们要实现多对多的删除操做呢?也就是删除用户的同时删除其对应的角色,实现的代码以下:
static void RemoveManyToMany() { using (var cxt = new ManyToManyRemoveContext()) { var user = cxt.Users.FirstOrDefault(x => x.Id == 1); var roles = new List<Role>(); roles.AddRange(user.Roles.Select(x => x)); foreach (var role in roles) { user.Roles.Remove(role); } cxt.Users.Remove(user); cxt.SaveChanges(); } }
运行结果如图:
好了,最后把Program.cs这个测试文件贴上来,供参考:
using EFRemoveManyToManyDemo.Model; using System; using System.Collections.Generic; using System.Linq; using static System.Console; namespace EFRemoveManyToManyDemo { public class Program { static void Main(string[] args) { //Update(); WriteLine("Before many to many removed"); Query(); RemoveManyToMany(); WriteLine("After many to many removed"); Query(); ReadKey(); } static void Query() { using (var cxt = new ManyToManyRemoveContext()) { var users = cxt.Users.ToList(); users.ForEach(x => { 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))); }); } } static void Add() { List<Role> roles; using (var cxt = new ManyToManyRemoveContext()) { roles = cxt.Roles.ToList(); cxt.Users.Add(new User { Id = 4, FirstName = "Console", LastName = "App", CreatedOn = DateTime.Now, Roles = roles.Where(x => x.Id == 1).ToList() }); } } static void Update() { using (var cxt = new ManyToManyRemoveContext()) { var user = cxt.Users.FirstOrDefault(x => x.Id == 3); user.FirstName = "ShuHao"; cxt.SaveChanges(); } } static void Remove() { using (var cxt = new ManyToManyRemoveContext()) { var user = cxt.Users.FirstOrDefault(x => x.Id == 2); cxt.Users.Remove(user); cxt.SaveChanges(); } } static void RemoveManyToMany() { using (var cxt = new ManyToManyRemoveContext()) { var user = cxt.Users.FirstOrDefault(x => x.Id == 1); var roles = new List<Role>(); roles.AddRange(user.Roles.Select(x => x)); foreach (var role in roles) { user.Roles.Remove(role); } cxt.Users.Remove(user); cxt.SaveChanges(); } } } }
若是须要完整的示例源码,请点击这里下载
本文原出处:图享网 --[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操做全程详细示例