Entity Framework Core 插入数据

这节我们主要了解使用EF Core向数据库中插入数据,同时EF Core可以单条插入也可以批量,插入数据时我们需要将实体的EntityState值设为"Added"状态

1 实体状态(EntityState)

EntityState枚举类型是用来存储实体状态,该枚举定义了下面5个值(Added,Deleted,Detached,Modified & Unchanged),当我们想要在数据库中创建一条新的记录时,EntityState值是Added,这将告诉EF Core我们将要插入记录,类似的如果我们想要更新一个实体时,EntityState值是Modified,删除实体时状态为Deleted,Unchanged状态表示实体没有任何改变,EF Core 会跟踪实体的变化,而Detached表示EF Core 没有启用实体跟踪

2 EF Core 新增数据

我们使用EF Core来创建一条记录,在应用程序Models文件下创建两个实体类Department & Employee,一个部门有多个员工,实体类如下:

public class Department
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Employee> Employee { get; set; }
}
public class Employee
{
    public int Id { get; set; }
    public int DepartmentId { get; set; }
    public string Name { 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; }
    public DbSet<Employee> Employee { get; set; }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    }
}

我们在启动文件中注册DbContext服务

builder.Services.AddDbContext<CompanyContext>(options =>
  options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));

上面的代码提供了DbContext使用的链接字符串(在appsettings文件中),同时也注册了DbContext服务,接下来我们在Controllers获取DbContext对象

下面的例子给出了链接字符串

{
   "ConnectionStrings": {
    "DefaultConnection": "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=EFCoreInsertRecords;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

3 向数据库中插入单挑数据

让我们展示一下如何在Department中创建一条记录,代码如下:

var dept = new Department()
{
    Name = "Designing"
};
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 = "Designing"
        };
        context.Entry(dept).State = EntityState.Added;
        context.SaveChanges();
    }
}

下面图片显示了最近创建的数据          

e8832942db5197225f856efe4099a598.png

我们也可以使用下面这种方式插入一条记录,和上面代码完成相同的功能

var dept = new Department()
{
    Name = "Designing"
};
context.Add(dept);
context.SaveChanges();

注意,我们不必将EntityState显式设置为Added,因为这是由EF Core自己完成

4 使用SaveChangesAsync()异步方法

我们使用SaveChanges()方法是同步的版本,可以使用异步版本SaveChangesAsync()替换同步版本,异步版本使线程能够更有效利用服务器资源,使我们的代码处理起来更顺畅而没有延迟

下面代码显示了异步方法在数据库中创建记录

var dept = new Department()
{
    Name = "Designing"
};
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, "", s => s.Name, s => s.DepartmentId, s => s.Designation))
{
    context.Employee.Add(emptyEmployee);
    await context.SaveChangesAsync();
    return RedirectToAction("Index");
}

6 EF Core 批量插入数据

使用DbContext.AddRange()方法向数据库中批量插入数据,这里批量插入3个部门记录

var dept1 = new Department() { Name = "Development" };
var dept2 = new Department() { Name = "HR" };
var dept3 = new Department() { Name = "Marketing" };
context.AddRange(dept1, dept2, dept3);
await context.SaveChangesAsync();

也可以使用下面这种写法:

var dept1 = new Department() { Name = "Development" };
var dept2 = new Department() { Name = "HR" };
var dept3 = new Department() { Name = "Marketing" };
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 = "Admin"
};
var emp = new Employee()
{
    Name = "Matt",
    Designation = "Head",
    Department = dept
};
context.Add(emp);
await context.SaveChangesAsync();

给Employee类的"Department"属性设置了一个新的对象,这种情况下EF Core知道关联的实体,因此它将插入到各自的表中

检查数据库发现两条记录在他们各自的表中 

65778b5a18c12eecae9771e990a97cd7.png

3ae1a21a587906c4f601dbc0f2871e86.png

8、EF Core CRUD 操作– 新增数据

使用EF Core 实现CRUD操作,我们先做一个新增数据功能针对Department实体类,在Controllers文件夹中创建DepartmentController.cs 类并添加Create方法,该方法从View提交的表单中获取一个新的Department

代码如下:

using EFCoreExample.Models;
using Microsoft.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);
            await context.SaveChangesAsync();
            return View();
        }
    }
}

通过依赖注入从Controller中获取DbContext对象并且使用它新增数据

下一步我们将创建一个表单,用户能输入部门名称,数据添加数据库中,因此我们添加一个razor文件叫Create.cshtml  Views/Department文件夹内,代码如下:

@{
    ViewData["Title"] = "Create Department";
}
@model Department
<form class="form-horizontal" role="form" method="post">
    <div class="mb-3 row">
        <label asp-for="Name" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Name" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <div class="col-sm-11 offset-sm-1">
            <button type="submit" class="btn btn-primary">保存</button>
            <button asp-action="Index" class="btn btn-secondary">
                返回
            </button>
        </div>
    </div>
</form>

运行应用程序,并在浏览器中输入url-https://localhost:7126

/Department/Create,我们将看到department表单

31889b8654f4b7a5948b16a5767cdc03.png

输入部门名称并点击保持创建一条新的记录

接下来我们需要创建Employee记录,因此我们添加一个新的Controller文件叫EmployeeController.cs,并且添加Create方法用来创建新的员工,代码如下:

using EFCoreExample.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.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("Index");
        }
    }
}

department和employee是一对多的关系,因此我们需要为每个员工插入一个department

我们获取部门数据并将其转换成List<SelectListItem>对象并将其添加到Viewbag变量中

List<SelectListItem> dept = new List<SelectListItem>();
dept = context.Department.Select(x => new SelectListItem { Text = x.Name, Value = x.Id.ToString() }).ToList();
ViewBag.Department = dept;

在View中我们读取Viewbag值并且展示在HTML的选择控件中,Create方法中也使用TryUpdateModelAsync方法,使用下面的代码替换原有的post版本Create方法

[HttpPost]
[ActionName("Create")]
public async Task<IActionResult> Create_Post()
{
    var emptyEmployee = new Employee();
    if (await TryUpdateModelAsync<Employee>(emptyEmployee, "", s => s.Name, s => s.DepartmentId, s => s.Designation))
    {
        context.Employee.Add(emptyEmployee);
        await context.SaveChangesAsync();
        return RedirectToAction("Index");
    }
    return View();
}

上面的代码我们创建一个空的员工对象并且添加了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["Title"] = "Create Employee";
}
@model Employee


<form method="post">
    <div class="mb-3 row">
        <label asp-for="Name" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Name" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <label asp-for="Department" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <select asp-for="DepartmentId" asp-items="ViewBag.Department" class="form-control"></select>
        </div>
    </div>
    <div class="mb-3 row">
        <label asp-for="Designation" class="col-sm-1 control-label"></label>
        <div class="col-sm-11">
            <input asp-for="Designation" class="form-control" />
        </div>
    </div>
    <div class="mb-3 row">
        <div class="col-sm-11 offset-sm-1">
            <button type="submit" class="btn btn-primary">保存</button>
            <button asp-action="Index" class="btn btn-secondary">
                返回
            </button>
        </div>
    </div>
</form>

使用下面代码显示所有部门:

<select asp-for="DepartmentId" asp-items="ViewBag.Department" class="form-control"></select>

运行应用程序并在浏览器中输入https://localhost:7018/

Employee/Create,我们看到employee表单使用Department显示在选择框内

7a7620e668cadfa49dffa19edac84131.png

总结:

我们学习了如何在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/

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值