ASP.NET?MVC+EF實現(xiàn)異步增刪改查
功能實現(xiàn)
我們以學生為例,實現(xiàn)增刪改查功能。
1、搭建UI層
我們這里使用ASP.NET MVC作為界面層顯示數(shù)據(jù),首先創(chuàng)建一個解決方案,然后添加一個MVC項目,命名為TaskAsync.UI,創(chuàng)建后的項目結(jié)構(gòu)如下圖所示:
2、添加實體類
我們把實體類放在單獨的類庫里面,新建一個類型項目,命名為TaskAsync.Model,里面有一個Student類,Student類代碼如下:
namespace TaskAsync.Model { /// <summary> /// 學生類 /// </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、添加服務接口層
我們把增刪改查的方法定義在接口里面,新添加一個類型項目,命名為TaskAsync.IService,需要引用上面創(chuàng)建的實體類庫。里面有一個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>類型的,方法名稱默認以Async結(jié)尾,標注為異步方法。
4、添加Entity Framework
我們使用EF作為ORM框架,把EF放在單獨類庫里面,命名為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不能省略,否則進行數(shù)據(jù)遷移的時候會報錯。
我們在TaskAsync.Data項目里面添加數(shù)據(jù)上下文類,繼承自父類的DbContext:
using System.Data.Entity; using TaskAsync.Model; namespace TaskAsync.Data { /// <summary> /// 數(shù)據(jù)上下文類,繼承自父類的DbContext /// </summary> public class AppDbContext:DbContext { /// <summary> /// 通過創(chuàng)建連接,給父類的構(gòu)造函數(shù)傳遞參數(shù) /// 參數(shù)是連接字符串的名稱 /// 表示使用連接字符串中名字為DbConnectionString的去連接數(shù)據(jù)庫 /// </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)建完成以后,我們接下來在程序包管理器控制臺里面進行數(shù)據(jù)遷移:
注意:項目要選擇EntityFramework所在的類庫項目。
1、開啟遷移
使用下面的命令開啟數(shù)據(jù)遷移:
Enable-Migrations
命令執(zhí)行如下圖所示:
2、增加遷移
使用下面的命令開始遷移:
Add-Migration Init
命令執(zhí)行如下圖所示:
執(zhí)行成功以后,會在TaskAsync.Data項目下面添加一個Migrations文件夾
這個文件夾下面有兩個類文件:Configuration.cs文件里面是配置信息,另外一個是本次遷移記錄文件。我們在Configuration.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ù)庫
我們在上面配置完成以后,就可以使用下面的命令去生成數(shù)據(jù)庫:
Update-Database
命令執(zhí)行如下圖所示:
命令執(zhí)行成功,就會自動創(chuàng)建數(shù)據(jù)庫和表,表里面插入我們添加的種子數(shù)據(jù):
5、添加接口的實現(xiàn)類
我們添加IStudentService接口的實現(xiàn)類。添加一個單獨的類庫,命名為TaskAsync.Service,并添加對TaskAsync.Model、TaskAsync.IService、TaskAsync.Data的引用,然后實現(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> /// 新增 方法標注為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、添加控制器
我們在ASP.NET MVC項目里面首先添加對上面幾個類庫的引用。
為了測試方法,我們直接添加一個包含視圖的MVC5控制器(使用Entity Framework),這樣就會自動生成UI界面了,如下圖所示:
模型類選擇Student,數(shù)據(jù)上下文類選擇AppDbContext,如下圖所示:
創(chuà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 // 為了防止“過多發(fā)布”攻擊,請啟用要綁定到的特定屬性,有關(guān) // 詳細信息,請參閱 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 // 為了防止“過多發(fā)布”攻擊,請啟用要綁定到的特定屬性,有關(guān) // 詳細信息,請參閱 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 // 為了防止“過多發(fā)布”攻擊,請啟用要綁定到的特定屬性,有關(guān) // 詳細信息,請參閱 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 // 為了防止“過多發(fā)布”攻擊,請啟用要綁定到的特定屬性,有關(guān) // 詳細信息,請參閱 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); //} } }
然后我們在修改_Layout.cshtml視圖文件,添加學生管理的一個標簽:
<!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 應用程序</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("應用程序名稱", "Index", "Home", new { area = "" }, new { @class = "navbar-brand" }) </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li>@Html.ActionLink("主頁", "Index", "Home")</li> <li>@Html.ActionLink("關(guān)于", "About", "Home")</li> <li>@Html.ActionLink("聯(lián)系方式", "Contact", "Home")</li> <li>@Html.ActionLink("學生管理", "Index", "Student")</li> </ul> </div> </div> </div> <div class="container body-content"> @RenderBody() <hr /> <footer> <p>? @DateTime.Now.Year - 我的 ASP.NET 應用程序</p> </footer> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/bootstrap") @RenderSection("scripts", required: false) </body> </html>
運行程序,點擊“學生管理”標簽,就可以看到列表數(shù)據(jù)了:
這樣我們就完成了一個ASP.NET MVC+EF實現(xiàn)異步增刪改查的方法了。 最終項目結(jié)構(gòu):
GitHub代碼地址:https://github.com/jxl1024/TaskAsync。
到此這篇關(guān)于ASP.NET MVC+EF實現(xiàn)異步增刪改查的文章就介紹到這了。希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- ASP.NET MVC5+EF6+EasyUI 后臺管理系統(tǒng)(81)-數(shù)據(jù)篩選(萬能查詢)實例
- ASP.NET MVC5+EF6+EasyUI后臺管理系統(tǒng) 微信公眾平臺開發(fā)之資源環(huán)境準備
- ASP.NET MVC5+EF6+EasyUI后臺管理系統(tǒng) 微信公眾平臺開發(fā)之消息管理
- ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后臺管理系統(tǒng)之前端頁面框架構(gòu)建源碼分享
- 基于mvc5+ef6+Bootstrap框架實現(xiàn)身份驗證和權(quán)限管理
- ASP.NET MVC+EF在服務端分頁使用jqGrid以及jquery Datatables的注意事項
- ASP.NET Mvc開發(fā)之EF延遲加載
- 一個簡單MVC5 + EF6示例分享
- 初識ASP.NET Mvc5+EF7的奇妙之旅
- ASP.NET MVC+EF框架+EasyUI實現(xiàn)權(quán)限管系列
相關(guān)文章
ASP.NET使用WebService實現(xiàn)天氣預報功能
這篇文章主要為大家詳細介紹了ASP.NET使用WebService實現(xiàn)天氣預報功能的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-08-08ASP.NET MVC使用EasyUI的datagrid多選提交保存教程
ASP.NET MVC使用EasyUI的datagrid多選提交保存教程,需要的朋友可以參考下。2011-12-12asp.net 計劃任務管理程序?qū)崿F(xiàn),多線程任務加載
b/s模式下用程序?qū)崿F(xiàn)計劃任務,一直是個不太好解決和管理的問題,當然可以采用ajax 計時器的方法模擬form端的timer事件。2009-11-11在ASP.NET Core Mvc集成MarkDown的方法
這篇文章主要介紹了在ASP.NET Core Mvc集成MarkDown的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-03-03建立自定義的數(shù)據(jù)驅(qū)動的本地化資源provider
本文探討了自定義的本地化資源提供者.如果想用一個可替代系統(tǒng)的資源處理方案,例如把所有的資源放入數(shù)據(jù)庫中,而不是放在分散的資源文件里,你可以自定義一個resource provider.2010-06-06asp.net中利用Jquery+Ajax+Json實現(xiàn)無刷新分頁的實例代碼
本篇文章主要是對asp.net中利用Jquery+Ajax+Json實現(xiàn)無刷新分頁的實例代碼進行了介紹,需要的朋友可以過來參考下,需要對大家有所幫助2014-02-02