|
这节我们主要了解使用EF Core向数据库中插入数据,同时EF Core可以单条插入也可以批量,插入数据时我们需要将实体的EntityState值设为"Added"状态
1 实体状态(EntityState)
EntityState枚举类型是用来存储实体状态,该枚举定义了下面5个值(Added,Deleted,Detached,Modified & Unchanged),当我们想要在数据库中创建一条新的记录时,EntityState值是Added,这将告诉EF Core我们将要插入记录,类似的如果我们想要更新一个实体时,EntityState值是Modified,删除实体时状态为Deleted,Unchanged状态表示实体没有任何改变,EFCore 会跟踪实体的变化,而Detached表示EF Core 没有启用实体跟踪
2 EFCore新增数据
我们使用EF Core来创建一条记录,在应用程序Models文件下创建两个实体类Department & Employee,一个部门有多个员工,实体类如下:
public class Department{ public int Id { get; set; }publicstringName{get;set;} public ICollection<Employee> Employee { get; set; }}publicclassEmployee{ public int Id { get; set; } public int DepartmentId { get; set; }publicstringName{get;set;} public string Designation { get; set; } public Department Department { get; set; }}导航属性是非常重要的属性,该属性定义了依赖或者相关联的实体,Department类中Employee属性
public ICollection Employee { get; set;}是一个拥有Employee实体集合的导航属性,Employee类Department属性
public Department Department { get; set; }这个导航属性引用了关联的Department实体
在应用程序的Models 文件夹下创建EF Core的DBContext 我们命名为CompanyContext.cs,这个类定义了两个实体Department和Employee
public class CompanyContext : DbContext{ public CompanyContext(DbContextOptions<CompanyContext> options) : base(options) {} public DbSet<Department> Department { get; set; }publicDbSet<Employee>Employee{get;set;} protected override void OnModelCreating(ModelBuilder modelBuilder){ }}我们在启动文件中注册DbContext服务
builder.Services.AddDbContext<CompanyContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString(&#34;DefaultConnection&#34;)));上面的代码提供了DbContext使用的链接字符串(在appsettings文件中),同时也注册了DbContext服务,接下来我们在Controllers获取DbContext对象
下面的例子给出了链接字符串
{ &#34;ConnectionStrings&#34;: { &#34;DefaultConnection&#34;: &#34;Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=EFCoreInsertRecords;Trusted_Connection=True;MultipleActiveResultSets=true&#34; }}3 向数据库中插入单挑数据
让我们展示一下如何在Department中创建一条记录,代码如下:
var dept = new Department(){ Name = &#34;Designing&#34;};context.Entry(dept).State = EntityState.Added;context.SaveChanges();我们创建了一个新的Department类的对象,并且设置EntityState状态Added,调用DbContext.SaveChanges()方法将会向Department表中插入一条数据,context变量是数据库的上下文对象,可以通过依赖注入从Controller中获取该对象,代码如下:
public class DepartmentController : Controller{ private CompanyContext context; public DepartmentController(CompanyContext cc) { context = cc; } //... action methods creating record public IActionResult Create() { var dept = new Department() { Name = &#34;Designing&#34; }; context.Entry(dept).State = EntityState.Added; context.SaveChanges(); }}下面图片显示了最近创建的数据

我们也可以使用下面这种方式插入一条记录,和上面代码完成相同的功能
var dept = new Department(){ Name = &#34;Designing&#34;};context.Add(dept);context.SaveChanges();注意,我们不必将EntityState显式设置为Added,因为这是由EF Core自己完成
4 使用SaveChangesAsync()异步方法
我们使用SaveChanges()方法是同步的版本,可以使用异步版本SaveChangesAsync()替换同步版本,异步版本使线程能够更有效利用服务器资源,使我们的代码处理起来更顺畅而没有延迟
下面代码显示了异步方法在数据库中创建记录
var dept = new Department(){ Name = &#34;Designing&#34;};context.Add(dept);await context.SaveChangesAsync();5 TryUpdateModelAsync
为了防止恶意用户过度提交新增数据最好方法是使用TryUpdateModelAsync方法,我们能从Model中提取字段的值并插入到数据库中,我们可以过滤不需要的字段,恶意用户使用一些工具来添加数据,例如:Fiddler或者通过JavaScript ,我们对数据做一层过滤,不让垃圾数据进入数据库
下面代码使用TryUpdateModelAsync方法添加一个新的员工记录,首先我们创建一个空的employee对象,通过lambda表达式从模型绑定中获取Name,DepartmentId和Designation的值并将它们插入到数据库中,剩下的字段全部忽略
var emptyEmployee = new Employee();if (await TryUpdateModelAsync<Employee>(emptyEmployee, &#34;&#34;, s => s.Name, s => s.DepartmentId, s => s.Designation)){ context.Employee.Add(emptyEmployee); await context.SaveChangesAsync(); return RedirectToAction(&#34;Index&#34;);}6 EF Core 批量插入数据
使用DbContext.AddRange()方法向数据库中批量插入数据,这里批量插入3个部门记录
var dept1 = new Department() { Name = &#34;Development&#34; };var dept2 = new Department() { Name = &#34;HR&#34; };var dept3 = new Department() { Name = &#34;Marketing&#34; };context.AddRange(dept1, dept2, dept3);awaitcontext.SaveChangesAsync();也可以使用下面这种写法:
var dept1 = new Department() { Name = &#34;Development&#34; };var dept2 = new Department() { Name = &#34;HR&#34; };var dept3 = new Department() { Name = &#34;Marketing&#34; };var deps = new List<Department>() { dept1, dept2, dept3 };context.AddRange(deps);await context.SaveChangesAsync();7 EF Core 插入关联数据
Department & Employee 表是一对多的关系,现在我们向每张表中插入新纪录(Department & Employee)
var dept = new Department(){ Name = &#34;Admin&#34;};var emp = new Employee(){ Name = &#34;Matt&#34;, Designation = &#34;Head&#34;, Department = dept};context.Add(emp);awaitcontext.SaveChangesAsync();给Employee类的&#34;Department&#34;属性设置了一个新的对象,这种情况下EF Core知道关联的实体,因此它将插入到各自的表中
检查数据库发现两条记录在他们各自的表中


8、EF Core CRUD 操作– 新增数据
使用EF Core 实现CRUD操作,我们先做一个新增数据功能针对Department实体类,在Controllers文件夹中创建DepartmentController.cs 类并添加Create方法,该方法从View提交的表单中获取一个新的Department
代码如下:
using EFCoreExample.Models;usingMicrosoft.AspNetCore.Mvc;namespace EFCoreExample.Controllers{ public class DepartmentController : Controller { private CompanyContext context; public DepartmentController(CompanyContext cc) { context = cc;} public IActionResult Create() { return View();} [HttpPost] public async Task<IActionResult> Create(Department dept) { context.Add(dept);awaitcontext.SaveChangesAsync(); return View(); } }}通过依赖注入从Controller中获取DbContext对象并且使用它新增数据
下一步我们将创建一个表单,用户能输入部门名称,数据添加数据库中,因此我们添加一个razor文件叫Create.cshtml Views/Department文件夹内,代码如下:
@{ ViewData[&#34;Title&#34;] = &#34;Create Department&#34;;}@model Department<form class=&#34;form-horizontal&#34; role=&#34;form&#34; method=&#34;post&#34;> <div class=&#34;mb-3 row&#34;> <label asp-for=&#34;Name&#34; class=&#34;col-sm-1 control-label&#34;></label> <div class=&#34;col-sm-11&#34;> <input asp-for=&#34;Name&#34; class=&#34;form-control&#34; /> </div> </div> <div class=&#34;mb-3 row&#34;> <div class=&#34;col-sm-11 offset-sm-1&#34;> <button type=&#34;submit&#34; class=&#34;btn btn-primary&#34;>保存</button> <button asp-action=&#34;Index&#34; class=&#34;btn btn-secondary&#34;> 返回 </button> </div> </div></form>运行应用程序,并在浏览器中输入url-https://localhost:7126
/Department/Create,我们将看到department表单

输入部门名称并点击保持创建一条新的记录
接下来我们需要创建Employee记录,因此我们添加一个新的Controller文件叫EmployeeController.cs,并且添加Create方法用来创建新的员工,代码如下:
using EFCoreExample.Models;using Microsoft.AspNetCore.Mvc;using Microsoft.AspNetCore.Mvc.Rendering;usingMicrosoft.EntityFrameworkCore;namespace EFCoreExample.Controllers{ public class EmployeeController : Controller { private CompanyContext context; public EmployeeController(CompanyContext cc) { context = cc;} public IActionResult Index() { return View();} public IActionResult Create() { List<SelectListItem> dept = new List<SelectListItem>(); dept = context.Department.Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }).ToList();ViewBag.Department=dept; return View();} [HttpPost] public async Task<IActionResult> Create(Employee emp) { context.Add(emp); await context.SaveChangesAsync(); return RedirectToAction(&#34;Index&#34;); } }}department和employee是一对多的关系,因此我们需要为每个员工插入一个department
我们获取部门数据并将其转换成List<SelectListItem>对象并将其添加到Viewbag变量中
List<SelectListItem> dept = new List<SelectListItem>();dept=context.Department.Select(x=>newSelectListItem{Text=x.Name,Value=x.Id.ToString()}).ToList();ViewBag.Department=dept;在View中我们读取Viewbag值并且展示在HTML的选择控件中,Create方法中也使用TryUpdateModelAsync方法,使用下面的代码替换原有的post版本Create方法
[HttpPost][ActionName(&#34;Create&#34;)]publicasyncTask<IActionResult>Create_Post(){varemptyEmployee=newEmployee();if(awaitTryUpdateModelAsync<Employee>(emptyEmployee,&#34;&#34;,s=>s.Name,s=>s.DepartmentId,s=>s.Designation)){context.Employee.Add(emptyEmployee);awaitcontext.SaveChangesAsync();returnRedirectToAction(&#34;Index&#34;);}returnView();}上面的代码我们创建一个空的员工对象并且添加了3个值-Name,DepartmentId和Designation 使用lambda表达式
s => s.Name, s => s.DepartmentId, s => s.Designation当razor表单被提交时通过模型绑定绑定employee的值,我们检查TryUpdateModelAsync 是否返回true,通过lambda表达式给emptyEmployee对象赋值,我们将emptyEmployee记录添加到context中,调用EF Core的SaveChangesAsync 方法将数据插入到数据库中
context.SaveChangesAsync();在Views/Employee文件夹内添加Create.cshtml文件,使用下面代码:
@{ ViewData[&#34;Title&#34;] = &#34;Create Employee&#34;;}@model Employee<form method=&#34;post&#34;> <div class=&#34;mb-3 row&#34;> <label asp-for=&#34;Name&#34; class=&#34;col-sm-1 control-label&#34;></label> <div class=&#34;col-sm-11&#34;> <input asp-for=&#34;Name&#34; class=&#34;form-control&#34; /> </div> </div> <div class=&#34;mb-3 row&#34;> <label asp-for=&#34;Department&#34; class=&#34;col-sm-1 control-label&#34;></label> <div class=&#34;col-sm-11&#34;> <select asp-for=&#34;DepartmentId&#34; asp-items=&#34;ViewBag.Department&#34; class=&#34;form-control&#34;></select> </div> </div> <div class=&#34;mb-3 row&#34;> <label asp-for=&#34;Designation&#34; class=&#34;col-sm-1 control-label&#34;></label> <div class=&#34;col-sm-11&#34;> <input asp-for=&#34;Designation&#34; class=&#34;form-control&#34; /> </div> </div> <div class=&#34;mb-3 row&#34;> <div class=&#34;col-sm-11 offset-sm-1&#34;> <button type=&#34;submit&#34; class=&#34;btn btn-primary&#34;>保存</button> <button asp-action=&#34;Index&#34; class=&#34;btn btn-secondary&#34;> 返回 </button> </div></div></form>使用下面代码显示所有部门:
<select asp-for=&#34;DepartmentId&#34; asp-items=&#34;ViewBag.Department&#34; class=&#34;form-control&#34;></select>运行应用程序并在浏览器中输入https://localhost:7018/
Employee/Create,我们看到employee表单使用Department显示在选择框内

总结:
我们学习了如何在EF Core 新增(单条和批量),也学习了如何插入关联表数据和创建CRUD特性,在下一节,我们讲解Entity Framework Core 读取数据
源代码地址:
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/EntityFrameworkCore/EFCoreInsertRecords
参考资料
https://www.yogihosting.com/migrations-entity-framework-core/
-
技术群:添加小编微信并备注进群
小编微信:mm1552923
公众号:dotNet编程大全
|
|