ASP.NET?MVC+EF實(shí)現(xiàn)異步增刪改查
功能實(shí)現(xiàn)
我們以學(xué)生為例,實(shí)現(xiàn)增刪改查功能。
1、搭建UI層
我們這里使用ASP.NET MVC作為界面層顯示數(shù)據(jù),首先創(chuàng)建一個(gè)解決方案,然后添加一個(gè)MVC項(xiàng)目,命名為TaskAsync.UI,創(chuàng)建后的項(xiàng)目結(jié)構(gòu)如下圖所示:

2、添加實(shí)體類
我們把實(shí)體類放在單獨(dú)的類庫(kù)里面,新建一個(gè)類型項(xiàng)目,命名為TaskAsync.Model,里面有一個(gè)Student類,Student類代碼如下:
namespace TaskAsync.Model
{
/// <summary>
/// 學(xué)生類
/// </summary>
public class Student
{
/// <summary>
/// 主鍵
/// </summary>
public int Id { get; set; }
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 年齡
/// </summary>
public int Age { get; set; }
/// <summary>
/// 性別
/// </summary>
public int Gender { get; set; }
}
}3、添加服務(wù)接口層
我們把增刪改查的方法定義在接口里面,新添加一個(gè)類型項(xiàng)目,命名為TaskAsync.IService,需要引用上面創(chuàng)建的實(shí)體類庫(kù)。里面有一個(gè)IStudentService接口,接口代碼如下:
using System.Collections.Generic;
using System.Threading.Tasks;
using TaskAsync.Model;
namespace TaskAsync.IService
{
public interface IStudentService
{
/// <summary>
/// 增加的異步方法
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
Task<int> AddPersonAsync(Student entity);
/// <summary>
/// 刪除的異步方法
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<int> DeleteByIdAsync(int id);
/// <summary>
/// 獲取所有數(shù)據(jù)
/// </summary>
/// <returns></returns>
Task<IEnumerable<Student>> GetAllAsync();
/// <summary>
/// 根據(jù)Id獲取單一值
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<Student> GetStudentByIdAsync(int id);
/// <summary>
/// 更新的異步方法
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
Task<int> UpdateAsync(Student entity);
}
}所有的方法返回值都是Task<T>類型的,方法名稱默認(rèn)以Async結(jié)尾,標(biāo)注為異步方法。
4、添加Entity Framework
我們使用EF作為ORM框架,把EF放在單獨(dú)類庫(kù)里面,命名為TaskAsync.Data。直接在NuGet里面安裝:

安裝完成以后,我們同樣需要在創(chuàng)建的ASP.NET MVC程序里面EntityFramework,然后在外層的Web.config文件里面添加鏈接字符串:
<connectionStrings>
<add name="EFContext" connectionString="Data Source=.;Initial Catalog=TaskAsyncDb;User ID=sa;Password=123456;" providerName="System.Data.SqlClient" />
</connectionStrings>注意:鏈接字符串里面的providerName不能省略,否則進(jìn)行數(shù)據(jù)遷移的時(shí)候會(huì)報(bào)錯(cuò)。
我們?cè)赥askAsync.Data項(xiàng)目里面添加數(shù)據(jù)上下文類,繼承自父類的DbContext:
using System.Data.Entity;
using TaskAsync.Model;
namespace TaskAsync.Data
{
/// <summary>
/// 數(shù)據(jù)上下文類,繼承自父類的DbContext
/// </summary>
public class AppDbContext:DbContext
{
/// <summary>
/// 通過(guò)創(chuàng)建連接,給父類的構(gòu)造函數(shù)傳遞參數(shù)
/// 參數(shù)是連接字符串的名稱
/// 表示使用連接字符串中名字為DbConnectionString的去連接數(shù)據(jù)庫(kù)
/// </summary>
public AppDbContext():base("name=DbConnectionString")
{
}
/// <summary>
/// 重寫OnModelCreating方法
/// </summary>
/// <param name="modelBuilder"></param>
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// 配置生成的表名
modelBuilder.Entity<Student>().ToTable("T_Student");
base.OnModelCreating(modelBuilder);
}
public DbSet<Student> Students { get; set; }
}
}數(shù)據(jù)上下文類創(chuàng)建完成以后,我們接下來(lái)在程序包管理器控制臺(tái)里面進(jìn)行數(shù)據(jù)遷移:

注意:項(xiàng)目要選擇EntityFramework所在的類庫(kù)項(xiàng)目。
1、開(kāi)啟遷移
使用下面的命令開(kāi)啟數(shù)據(jù)遷移:
Enable-Migrations
命令執(zhí)行如下圖所示:

2、增加遷移
使用下面的命令開(kāi)始遷移:
Add-Migration Init
命令執(zhí)行如下圖所示:

執(zhí)行成功以后,會(huì)在TaskAsync.Data項(xiàng)目下面添加一個(gè)Migrations文件夾

這個(gè)文件夾下面有兩個(gè)類文件:Configuration.cs文件里面是配置信息,另外一個(gè)是本次遷移記錄文件。我們?cè)贑onfiguration.cs類里面添加一些種子數(shù)據(jù):
namespace TaskAsync.Data.Migrations
{
using System.Collections.Generic;
using System.Data.Entity.Migrations;
using System.Linq;
using TaskAsync.Model;
internal sealed class Configuration : DbMigrationsConfiguration<TaskAsync.Data.AppDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
}
protected override void Seed(TaskAsync.Data.AppDbContext context)
{
List<Student> list = new List<Student>()
{
new Student()
{
Name="Jack",
Age=23,
Gender=1
},
new Student()
{
Name="Tom",
Age=25,
Gender=2
}
};
if(!context.Students.Any())
{
context.Students.AddRange(list);
}
}
}
}3、生成數(shù)據(jù)庫(kù)
我們?cè)谏厦媾渲猛瓿梢院?,就可以使用下面的命令去生成?shù)據(jù)庫(kù):
Update-Database
命令執(zhí)行如下圖所示:

命令執(zhí)行成功,就會(huì)自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)和表,表里面插入我們添加的種子數(shù)據(jù):

5、添加接口的實(shí)現(xiàn)類
我們添加IStudentService接口的實(shí)現(xiàn)類。添加一個(gè)單獨(dú)的類庫(kù),命名為TaskAsync.Service,并添加對(duì)TaskAsync.Model、TaskAsync.IService、TaskAsync.Data的引用,然后實(shí)現(xiàn)IStudentService接口:
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TaskAsync.Data;
using TaskAsync.IService;
using TaskAsync.Model;
namespace TaskAsync.Service
{
public class StudentService : IStudentService
{
/// <summary>
/// 新增 方法標(biāo)注為async
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public async Task<int> AddPersonAsync(Student entity)
{
using (AppDbContext dbContext = new AppDbContext())
{
dbContext.Students.Add(entity);
// 調(diào)用異步方法
int count = await dbContext.SaveChangesAsync();
return count;
}
}
/// <summary>
/// 刪除
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<int> DeleteByIdAsync(int id)
{
using (AppDbContext dbContext = new AppDbContext())
{
Student student =await dbContext.Students.FindAsync(new object[] { id });
if(student!=null)
{
dbContext.Students.Remove(student);
return await dbContext.SaveChangesAsync();
}
else
{
return 0;
}
}
}
public async Task<IEnumerable<Student>> GetAllAsync()
{
List<Student> list = await Task.Run<List<Student>>(() =>
{
using (AppDbContext dbContext = new AppDbContext())
{
return dbContext.Students.ToList();
}
});
return list;
}
public async Task<Student> GetStudentByIdAsync(int id)
{
using (AppDbContext dbContext = new AppDbContext())
{
Student student = await dbContext.Students.FindAsync(new object[] { id });
if (student != null)
{
return student
}
else
{
return null;
}
}
}
public async Task<int> UpdateAsync(Student entity)
{
using (AppDbContext dbContext = new AppDbContext())
{
Student student = await dbContext.Students.FindAsync(new object[] { entity.Id });
if (student != null)
{
student.Name = entity.Name;
student.Age = entity.Age;
student.Gender = entity.Gender;
dbContext.Entry(student).State = System.Data.Entity.EntityState.Modified;
return await dbContext.SaveChangesAsync();
}
else
{
return 0;
}
}
}
}
}注意:這里同樣需要添加到EntityFramework的引用。
6、添加控制器
我們?cè)贏SP.NET MVC項(xiàng)目里面首先添加對(duì)上面幾個(gè)類庫(kù)的引用。
為了測(cè)試方法,我們直接添加一個(gè)包含視圖的MVC5控制器(使用Entity Framework),這樣就會(huì)自動(dòng)生成UI界面了,如下圖所示:

模型類選擇Student,數(shù)據(jù)上下文類選擇AppDbContext,如下圖所示:

創(chuàng)建完成之后,會(huì)看到自動(dòng)添加了視圖:

控制器里也自動(dòng)生成了代碼:
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using TaskAsync.Data;
using TaskAsync.Model;
namespace TaskAsync.UI.Controllers
{
public class StudentController : Controller
{
private AppDbContext db = new AppDbContext();
// GET: Student
public ActionResult Index()
{
return View(db.Students.ToList());
}
// GET: Student/Details/5
public ActionResult Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// GET: Student/Create
public ActionResult Create()
{
return View();
}
// POST: Student/Create
// 為了防止“過(guò)多發(fā)布”攻擊,請(qǐng)啟用要綁定到的特定屬性,有關(guān)
// 詳細(xì)信息,請(qǐng)參閱 https://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Include = "Id,Name,Age,Gender")] Student student)
{
if (ModelState.IsValid)
{
db.Students.Add(student);
db.SaveChanges();
return RedirectToAction("Index");
}
return View(student);
}
// GET: Student/Edit/5
public ActionResult Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// POST: Student/Edit/5
// 為了防止“過(guò)多發(fā)布”攻擊,請(qǐng)啟用要綁定到的特定屬性,有關(guān)
// 詳細(xì)信息,請(qǐng)參閱 https://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "Id,Name,Age,Gender")] Student student)
{
if (ModelState.IsValid)
{
db.Entry(student).State = EntityState.Modified;
db.SaveChanges();
return RedirectToAction("Index");
}
return View(student);
}
// GET: Student/Delete/5
public ActionResult Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = db.Students.Find(id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// POST: Student/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
Student student = db.Students.Find(id);
db.Students.Remove(student);
db.SaveChanges();
return RedirectToAction("Index");
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
}
}
}但是框架生成的代碼都是同步方法的,不是我們需要的,我們改成異步的方法:
using System.Data.Entity;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Mvc;
using TaskAsync.Data;
using TaskAsync.IService;
using TaskAsync.Model;
using TaskAsync.Service;
namespace TaskAsync.UI.Controllers
{
public class StudentController : Controller
{
//private AppDbContext db = new AppDbContext();
IStudentService service = new StudentService();
// GET: Student
public async Task<ActionResult> Index()
{
return View(await service.GetAllAsync());
}
// GET: Student/Details/5
public async Task<ActionResult> Details(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student =await service.GetStudentByIdAsync((int)id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// GET: Student/Create
public ActionResult Create()
{
return View();
}
// POST: Student/Create
// 為了防止“過(guò)多發(fā)布”攻擊,請(qǐng)啟用要綁定到的特定屬性,有關(guān)
// 詳細(xì)信息,請(qǐng)參閱 https://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create([Bind(Include = "Id,Name,Age,Gender")] Student student)
{
if (ModelState.IsValid)
{
int count = await service.AddPersonAsync(student);
if(count>0)
{
return RedirectToAction("Index");
}
}
return View(student);
}
// GET: Student/Edit/5
public async Task<ActionResult> Edit(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = await service.GetStudentByIdAsync((int)id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// POST: Student/Edit/5
// 為了防止“過(guò)多發(fā)布”攻擊,請(qǐng)啟用要綁定到的特定屬性,有關(guān)
// 詳細(xì)信息,請(qǐng)參閱 https://go.microsoft.com/fwlink/?LinkId=317598。
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Edit([Bind(Include = "Id,Name,Age,Gender")] Student student)
{
if (ModelState.IsValid)
{
int count = await service.UpdateAsync(student);
if (count > 0)
{
return RedirectToAction("Index");
}
}
return View(student);
}
// GET: Student/Delete/5
public async Task<ActionResult> Delete(int? id)
{
if (id == null)
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
Student student = await service.GetStudentByIdAsync((int)id);
if (student == null)
{
return HttpNotFound();
}
return View(student);
}
// POST: Student/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public async Task<ActionResult> DeleteConfirmed(int id)
{
int count = await service.DeleteByIdAsync(id);
return RedirectToAction("Index");
}
//protected override void Dispose(bool disposing)
//{
// if (disposing)
// {
// db.Dispose();
// }
// base.Dispose(disposing);
//}
}
}然后我們?cè)谛薷腳Layout.cshtml視圖文件,添加學(xué)生管理的一個(gè)標(biāo)簽:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>@ViewBag.Title - 我的 ASP.NET 應(yīng)用程序</title>
@Styles.Render("~/Content/css")
@Scripts.Render("~/bundles/modernizr")
</head>
<body>
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
@Html.ActionLink("應(yīng)用程序名稱", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" })
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li>@Html.ActionLink("主頁(yè)", "Index", "Home")</li>
<li>@Html.ActionLink("關(guān)于", "About", "Home")</li>
<li>@Html.ActionLink("聯(lián)系方式", "Contact", "Home")</li>
<li>@Html.ActionLink("學(xué)生管理", "Index", "Student")</li>
</ul>
</div>
</div>
</div>
<div class="container body-content">
@RenderBody()
<hr />
<footer>
<p>? @DateTime.Now.Year - 我的 ASP.NET 應(yīng)用程序</p>
</footer>
</div>
@Scripts.Render("~/bundles/jquery")
@Scripts.Render("~/bundles/bootstrap")
@RenderSection("scripts", required: false)
</body>
</html>運(yùn)行程序,點(diǎn)擊“學(xué)生管理”標(biāo)簽,就可以看到列表數(shù)據(jù)了:

這樣我們就完成了一個(gè)ASP.NET MVC+EF實(shí)現(xiàn)異步增刪改查的方法了。 最終項(xiàng)目結(jié)構(gòu):

GitHub代碼地址:https://github.com/jxl1024/TaskAsync。
到此這篇關(guān)于ASP.NET MVC+EF實(shí)現(xiàn)異步增刪改查的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- ASP.NET MVC5+EF6+EasyUI 后臺(tái)管理系統(tǒng)(81)-數(shù)據(jù)篩選(萬(wàn)能查詢)實(shí)例
- ASP.NET MVC5+EF6+EasyUI后臺(tái)管理系統(tǒng) 微信公眾平臺(tái)開(kāi)發(fā)之資源環(huán)境準(zhǔn)備
- ASP.NET MVC5+EF6+EasyUI后臺(tái)管理系統(tǒng) 微信公眾平臺(tái)開(kāi)發(fā)之消息管理
- ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后臺(tái)管理系統(tǒng)之前端頁(yè)面框架構(gòu)建源碼分享
- 基于mvc5+ef6+Bootstrap框架實(shí)現(xiàn)身份驗(yàn)證和權(quán)限管理
- ASP.NET MVC+EF在服務(wù)端分頁(yè)使用jqGrid以及jquery Datatables的注意事項(xiàng)
- ASP.NET Mvc開(kāi)發(fā)之EF延遲加載
- 一個(gè)簡(jiǎn)單MVC5 + EF6示例分享
- 初識(shí)ASP.NET Mvc5+EF7的奇妙之旅
- ASP.NET MVC+EF框架+EasyUI實(shí)現(xiàn)權(quán)限管系列
相關(guān)文章
asp.net用Zxing庫(kù)實(shí)現(xiàn)條形碼輸出的具體實(shí)現(xiàn)
這篇文章主要介紹了asp.net用Zxing庫(kù)實(shí)現(xiàn)條形碼輸出的具體實(shí)現(xiàn),有需要的朋友可以參考一下2013-12-12
.net控件dropdownlist動(dòng)態(tài)綁定數(shù)據(jù)具體過(guò)程分解
一、在頁(yè)面初始化時(shí)候?qū)⒓辖壎ǖ紻ropDownList;二、在頁(yè)面初始化的時(shí)候向DropDownList添加數(shù)據(jù);三、將DataReader讀取的數(shù)據(jù)動(dòng)態(tài)綁定到DropDownList等等2013-05-05
ASP.NET中UpdatePanel與jQuery同時(shí)使用所遇問(wèn)題解決
在.NET中使用了UpdatePanel,里面的輸入框使用了jQuery的日歷選擇器,接下來(lái)介紹下兩者同時(shí)使用的一些細(xì)節(jié)及問(wèn)題的解決方法,感興趣的各位可以參考下哈2013-03-03
在asp.net core中使用類似Application的服務(wù)的實(shí)現(xiàn)
這篇文章主要介紹了在asp.net core中使用類似Application的服務(wù)的實(shí)現(xiàn),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-02-02
vb.net借助剪貼板將圖片導(dǎo)入excel內(nèi)
這篇文章主要介紹了vb.net將圖片導(dǎo)入到excel的方法,只要借助剪貼板將圖片粘貼到excel中就可以完成了,大家參考使用吧2014-01-01
CodeFirst從零開(kāi)始搭建Asp.Net Core2.0網(wǎng)站
這篇文章主要為大家詳細(xì)介紹了CodeFirst從零開(kāi)始搭建Asp.Net Core2.0網(wǎng)站的詳細(xì)過(guò)程,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07

