[C#.NET]EntityFramework(EF)CodeFirst多对多关系的实体增。。。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
[C#.NET]EntityFramework(EF)CodeFirst多对多关系的实体增。
本⽂我们来学习⼀下在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
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()
{
ers = new HashSet<User>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<User> Users { get; set; }
}
}
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 => stName).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 => ).HasMaxLength(50).IsRequired();
HasMany(x => ers)
.WithMany(x => x.Roles)
.Map(m =>
{
m.MapLeftKey("RoleId");
m.MapRightKey("UserId");
m.ToTable("LNK_User_Role");
});
}
}
}
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 /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⽂件的代码:
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所实体⽣成到配置好的数据库中。
第三步、应⽤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是我们指定的本次数据迁移的版本名称,⽂件中的内容如下:
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(
"er",
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, erId })
.ForeignKey("dbo.Role", t => t.RoleId, cascadeDelete: true)
.ForeignKey("er", t => erId, cascadeDelete: true)
.Index(t => t.RoleId)
.Index(t => erId);
}
public override void Down()
{
DropForeignKey("dbo.LNK_User_Role", "UserId", "er");
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("er");
DropTable("dbo.Role");
}
}
}
我们可以通过这个⽂件中的内容看到,有Up()和Down()这两个⽅法,Up()⽅法要执⾏的其实就是本次数据迁移要对数据进⾏的操作,⽽Down()⽅法则是在以后我们如果要退回到此版本应该执⾏的操作。
经过以上两个命令,如你迫不及待地要去数据库管理⼯具中查看有⼀个名叫:ManyToManyRemoveDemo的数据库是否已⽣成,那么很遗憾地告诉你,还没有。
这时,我们还得执⾏最后⼀个命令来⽣成数据库和实体对应的表。
3.3 Update-Database -Verbose
执⾏以上命令,我们这时再打开数据库管理⼯具。
没错ManyToManyRemoveDemo就在那⾥。
再查看表是否成功⽣成呢,再检查⼀下表中是否有我们初始化的数据呢,没错,这些都是可以有的。
怎么样,惊喜吧,欢呼吧,我们做到了
但还没完,请先回复平静,这还只是⼀个开始。
Entity Framework还可以做得更多,我们需要学习的也还有很多,编程的道路从来就不是⼀步到位的,得有个过程。
⼀步⼀步往下看吧。
第四步、增、删、改、查操作
4.1 查询数据⽰例
打开我们项⽬的Program.cs⽂件。
⾸先,我们来查询(Query)⼀下数据库中的数据,如下:
static void Main(string[] args)
{
Query();
ReadKey();
}
static void Query()
{
using (var cxt = new ManyToManyRemoveContext())
{
var users = ers.ToList();
users.ForEach(x =>
{
WriteLine("User First Name:{0},Last Name:{1},Create On:{2}\n |__Roles:{3}", x.FirstName, stName, x.CreatedOn, string.Join(",", x.Roles.Select(r => )));
});
}
}
运⾏结果如图:
4.2 更新数据⽰例
再来更新⼀条数据库中的数据怎么样,如下:
static void Main(string[] args)
{
Update();
Query();
ReadKey();
}
static void Query()
{
using (var cxt = new ManyToManyRemoveContext())
{
var users = ers.ToList();
users.ForEach(x =>
{
WriteLine("User First Name:{0},Last Name:{1},Create On:{2}\n |__Roles:{3}", x.FirstName, stName, x.CreatedOn, string.Join(",", x.Roles.Select(r => )));
});
}
}
static void Update()
{
using (var cxt = new ManyToManyRemoveContext())
{
var user = ers.FirstOrDefault(x=>x.Id==3);
user.FirstName = "ShuHao";
cxt.SaveChanges();
}
}
运⾏结果如我们所料,如图:
4.3 删除数据⽰例
Id为3的User的FirstName已经从数据库更新了。
同样的,我们要完成删除操作也⽐较简,如下:
static void Remove()
{
using (var cxt = new ManyToManyRemoveContext())
{
var user = ers.FirstOrDefault(x=>x.Id==2);
ers.Remove(user);
cxt.SaveChanges();
}
}
4.4 新增数据⽰例
就不再贴图了。
最后是添加操作,向User表添加⼀个⽤户并分配⼀个Id为1的⾓⾊,代码如下:
static void Add()
{
List<Role> roles;
using (var cxt = new ManyToManyRemoveContext())
{
roles = cxt.Roles.ToList();
ers.Add(new User
{
Id = 4,
FirstName = "Console",
LastName = "App",
CreatedOn = DateTime.Now,
Roles = roles.Where(x => x.Id == 1).ToList()
});
}
}
4.5 删除多对多数据的⽰例
好了,以上是对User(⽤户实体)进⾏简单的增、删、改、查的操作,那么我们要实现多对多的删除操作呢?也就是删除⽤户的同时删除其对应的⾓⾊,实现的代码如下:static void RemoveManyToMany()
{
using (var cxt = new ManyToManyRemoveContext())
{
var user = ers.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);
}
ers.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 = ers.ToList();
users.ForEach(x =>
{
WriteLine("User First Name:{0},Last Name:{1},Create On:{2}\n |__Roles:{3}", x.FirstName, stName, x.CreatedOn, string.Join(",", x.Roles.Select(r => ))); });
}
}
static void Add()
{
List<Role> roles;
using (var cxt = new ManyToManyRemoveContext())
{
roles = cxt.Roles.ToList();
ers.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 = ers.FirstOrDefault(x => x.Id == 3);
user.FirstName = "ShuHao";
cxt.SaveChanges();
}
}
static void Remove()
{
using (var cxt = new ManyToManyRemoveContext())
{
var user = ers.FirstOrDefault(x => x.Id == 2);
ers.Remove(user);
cxt.SaveChanges();
}
}
static void RemoveManyToMany()
{
using (var cxt = new ManyToManyRemoveContext())
{
var user = ers.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);
}
ers.Remove(user);
cxt.SaveChanges();
}
}
}
}
如果需要完整的⽰例源码,。