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)目,命名為T(mén)askAsync.UI,創(chuàng)建后的項(xiàng)目結(jié)構(gòu)如下圖所示:
2、添加實(shí)體類(lèi)
我們把實(shí)體類(lèi)放在單獨(dú)的類(lèi)庫(kù)里面,新建一個(gè)類(lèi)型項(xiàng)目,命名為T(mén)askAsync.Model,里面有一個(gè)Student類(lèi),Student類(lèi)代碼如下:
namespace TaskAsync.Model { /// <summary> /// 學(xué)生類(lèi) /// </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è)類(lèi)型項(xiàng)目,命名為T(mén)askAsync.IService,需要引用上面創(chuàng)建的實(shí)體類(lèi)庫(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>類(lèi)型的,方法名稱(chēng)默認(rèn)以Async結(jié)尾,標(biāo)注為異步方法。
4、添加Entity Framework
我們使用EF作為ORM框架,把EF放在單獨(dú)類(lèi)庫(kù)里面,命名為T(mén)askAsync.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ù)上下文類(lèi),繼承自父類(lèi)的DbContext:
using System.Data.Entity; using TaskAsync.Model; namespace TaskAsync.Data { /// <summary> /// 數(shù)據(jù)上下文類(lèi),繼承自父類(lèi)的DbContext /// </summary> public class AppDbContext:DbContext { /// <summary> /// 通過(guò)創(chuàng)建連接,給父類(lèi)的構(gòu)造函數(shù)傳遞參數(shù) /// 參數(shù)是連接字符串的名稱(chēng) /// 表示使用連接字符串中名字為DbConnectionString的去連接數(shù)據(jù)庫(kù) /// </summary> public AppDbContext():base("name=DbConnectionString") { } /// <summary> /// 重寫(xiě)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ù)上下文類(lèi)創(chuàng)建完成以后,我們接下來(lái)在程序包管理器控制臺(tái)里面進(jìn)行數(shù)據(jù)遷移:
注意:項(xiàng)目要選擇EntityFramework所在的類(lèi)庫(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è)類(lèi)文件:Configuration.cs文件里面是配置信息,另外一個(gè)是本次遷移記錄文件。我們?cè)贑onfiguration.cs類(lèi)里面添加一些種子數(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)類(lèi)
我們添加IStudentService接口的實(shí)現(xiàn)類(lèi)。添加一個(gè)單獨(dú)的類(lèi)庫(kù),命名為T(mén)askAsync.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è)類(lèi)庫(kù)的引用。
為了測(cè)試方法,我們直接添加一個(gè)包含視圖的MVC5控制器(使用Entity Framework),這樣就會(huì)自動(dòng)生成UI界面了,如下圖所示:
模型類(lèi)選擇Student,數(shù)據(jù)上下文類(lèi)選擇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)用程序名稱(chē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)能查詢(xú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使用WebService實(shí)現(xiàn)天氣預(yù)報(bào)功能
這篇文章主要為大家詳細(xì)介紹了ASP.NET使用WebService實(shí)現(xiàn)天氣預(yù)報(bào)功能的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-08-08詳解.NET Core中的數(shù)據(jù)保護(hù)組件
在本篇文章中我們給大家整理了關(guān)于返回主頁(yè).NET Core中的數(shù)據(jù)保護(hù)組件的相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們參考下。2018-09-09ASP.NET MVC使用EasyUI的datagrid多選提交保存教程
ASP.NET MVC使用EasyUI的datagrid多選提交保存教程,需要的朋友可以參考下。2011-12-12asp.net 計(jì)劃任務(wù)管理程序?qū)崿F(xiàn),多線程任務(wù)加載
b/s模式下用程序?qū)崿F(xiàn)計(jì)劃任務(wù),一直是個(gè)不太好解決和管理的問(wèn)題,當(dāng)然可以采用ajax 計(jì)時(shí)器的方法模擬form端的timer事件。2009-11-11asp.net上傳圖片并作處理水印與縮略圖的實(shí)例代碼
asp.net 上傳圖片并作處理(生成縮略圖 、在圖片上增加文字水印、在圖片上生成圖片水印)的實(shí)例代碼,經(jīng)過(guò)測(cè)試!2013-06-06在ASP.NET Core Mvc集成MarkDown的方法
這篇文章主要介紹了在ASP.NET Core Mvc集成MarkDown的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03c# 可變數(shù)目參數(shù)params實(shí)例
一般來(lái)說(shuō),參數(shù)個(gè)數(shù)都是固定的,定義為集群類(lèi)型的參數(shù)可以實(shí)現(xiàn)可變數(shù)目參數(shù)的目的,但是.NET提供了更靈活的機(jī)制來(lái)實(shí)現(xiàn)可變數(shù)目參數(shù),這就是使用params修飾符2012-11-11建立自定義的數(shù)據(jù)驅(qū)動(dòng)的本地化資源provider
本文探討了自定義的本地化資源提供者.如果想用一個(gè)可替代系統(tǒng)的資源處理方案,例如把所有的資源放入數(shù)據(jù)庫(kù)中,而不是放在分散的資源文件里,你可以自定義一個(gè)resource provider.2010-06-06asp.net中利用Jquery+Ajax+Json實(shí)現(xiàn)無(wú)刷新分頁(yè)的實(shí)例代碼
本篇文章主要是對(duì)asp.net中利用Jquery+Ajax+Json實(shí)現(xiàn)無(wú)刷新分頁(yè)的實(shí)例代碼進(jìn)行了介紹,需要的朋友可以過(guò)來(lái)參考下,需要對(duì)大家有所幫助2014-02-02