当前位置 : 主页 > 网络编程 > ASP >

ASP.NET MVC+EF实现异步增删改查

来源:互联网 收集:自由互联 发布时间:2023-01-30
目录 功能实现 1、搭建UI层 2、添加实体类 3、添加服务接口层 4、添加Entity Framework 1、开启迁移 2、增加迁移 3、生成数据库 5、添加接口的实现类 6、添加控制器 功能实现 我们以学生为
目录
  • 功能实现
  • 1、搭建UI层
  • 2、添加实体类
  • 3、添加服务接口层
  • 4、添加Entity Framework
    • 1、开启迁移
    • 2、增加迁移
    • 3、生成数据库
  • 5、添加接口的实现类
    • 6、添加控制器

      功能实现

      我们以学生为例,实现增删改查功能。

      1、搭建UI层

      我们这里使用ASP.NET MVC作为界面层显示数据,首先创建一个解决方案,然后添加一个MVC项目,命名为TaskAsync.UI,创建后的项目结构如下图所示:

      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,需要引用上面创建的实体类库。里面有一个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>
              /// 获取所有数据
              /// </summary>
              /// <returns></returns>
              Task<IEnumerable<Student>> GetAllAsync();
      
              /// <summary>
              /// 根据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结尾,标注为异步方法。

      4、添加Entity Framework

      我们使用EF作为ORM框架,把EF放在单独类库里面,命名为TaskAsync.Data。直接在NuGet里面安装:

      安装完成以后,我们同样需要在创建的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不能省略,否则进行数据迁移的时候会报错。

      我们在TaskAsync.Data项目里面添加数据上下文类,继承自父类的DbContext:

      using System.Data.Entity;
      using TaskAsync.Model;
      
      namespace TaskAsync.Data
      {
          /// <summary>
          /// 数据上下文类,继承自父类的DbContext
          /// </summary>
          public class AppDbContext:DbContext
          {
              /// <summary>
              /// 通过创建连接,给父类的构造函数传递参数
              /// 参数是连接字符串的名称
              /// 表示使用连接字符串中名字为DbConnectionString的去连接数据库
              /// </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; }
          }
      }

      数据上下文类创建完成以后,我们接下来在程序包管理器控制台里面进行数据迁移:

      注意:项目要选择EntityFramework所在的类库项目。

      1、开启迁移

      使用下面的命令开启数据迁移:

      Enable-Migrations

      命令执行如下图所示:

      2、增加迁移

      使用下面的命令开始迁移:

      Add-Migration Init

      命令执行如下图所示:

      执行成功以后,会在TaskAsync.Data项目下面添加一个Migrations文件夹

      这个文件夹下面有两个类文件:Configuration.cs文件里面是配置信息,另外一个是本次迁移记录文件。我们在Configuration.cs类里面添加一些种子数据:

      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、生成数据库

      我们在上面配置完成以后,就可以使用下面的命令去生成数据库:

      Update-Database

      命令执行如下图所示:

      命令执行成功,就会自动创建数据库和表,表里面插入我们添加的种子数据:

      5、添加接口的实现类

      我们添加IStudentService接口的实现类。添加一个单独的类库,命名为TaskAsync.Service,并添加对TaskAsync.Model、TaskAsync.IService、TaskAsync.Data的引用,然后实现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);
                      // 调用异步方法
                      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,数据上下文类选择AppDbContext,如下图所示:

      创建完成之后,会看到自动添加了视图:

      控制器里也自动生成了代码:

      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
              // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
              // 详细信息,请参阅 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
              // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
              // 详细信息,请参阅 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
              // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
              // 详细信息,请参阅 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
              // 为了防止“过多发布”攻击,请启用要绑定到的特定属性,有关 
              // 详细信息,请参阅 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("关于", "About", "Home")</li>
                          <li>@Html.ActionLink("联系方式", "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>

      运行程序,点击“学生管理”标签,就可以看到列表数据了:

      这样我们就完成了一个ASP.NET MVC+EF实现异步增删改查的方法了。 最终项目结构:

      GitHub代码地址:https://github.com/jxl1024/TaskAsync。

      到此这篇关于ASP.NET MVC+EF实现异步增删改查的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持自由互联。

      网友评论