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

目录
  • 功能实现
  • 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实现异步增删改查的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 一个简单MVC5 + EF6示例分享

    本文所使用的软件及环境: Visual Studio Ultimate 2013; MVC5 + EF6 + .NET Framework 4.5 + LocalDB;Windows 7 x64 Professional 说明: 1.在EF (Entity Framework,以下简称EF6)框架下,操作数据的方式有三种:Database First, Model First, 以及 Code First,本文基于Code First创建. 2.本文是基于MVC5创建: 3.LocalDB Lo

  • ASP.NET MVC5+EF6+EasyUI后台管理系统 微信公众平台开发之消息管理

    前言 回顾上一节,我们熟悉的了解了消息的请求和响应,这一节我们来建立数据库的表,表的设计蛮复杂 你也可以按自己所分析的情形结构来建表 必须非常熟悉表的结果才能运用这张表,这表表的情形涵盖比较多 思维导图 我这个人比较喜欢用思维导图来分析和表达一些模型: 表结构  根据思维导图,我们可以建立的表可以是3张表:消息表,规则表,类型表 消息表:实际的消息 规则表:文本.图文.语音等 类型表:文本.图文.语音(默认回复,订阅回复) 也可以是两张表:规制表,消息表(+一个类型字段) 我这里只设计一张表:消

  • 基于mvc5+ef6+Bootstrap框架实现身份验证和权限管理

    近和朋友完成了一个大单子架构是mvc5+ef6+Bootstrap,用的是vs2015,数据库是sql server2014.朋友做的架构,项目完成后觉得很多值得我学习,在这里总结下一些心得. 创建项目一开始删掉App_Start目录下的IdentityConfig.cs和Startup.Auth.cs文件;清空Modle文件夹,Controller文件夹和相应的View; 删除目录下的ApplicationInsights.config文件和Startup.cs文件 修改web.config文

  • ASP.NET MVC5+EF6+EasyUI后台管理系统 微信公众平台开发之资源环境准备

    前言: 本次将学习扩展企业微信公众号功能,微信公众号也是企业流量及品牌推广的主要途径,所谓工欲善其事必先利其器,调试微信必须把程序发布外网环境,导致调试速度太慢,太麻烦! 我们需要准备妥当才能进入开发,为后续快速开发作准备 什么是内网穿透? 意在外部网络通过域名可以访问本地IIS站点! 软件环境: Windows10+IIS10 (把本地站点配置到IIS10做为备用,发布站点不作为教程) 知识点:花生壳(主要)ngrok开始: 首先发布站点到IIS,我这里发布站点到本地IIS,并绑定端口为:80

  • ASP.NET MVC+EF在服务端分页使用jqGrid以及jquery Datatables的注意事项

    一直想自己做个博客网站,技术路线是用ASN.NET MVC5+EF6(Code First)+ZUI+各种Jquery插件,有了这个想法之后就开始选择UI,看了好多bootstrap的模板之后,发现即使你用了bootstrap还是要自己写css样式,都是自学的,前端真的很垃圾,在网上找了很多UI,以下是各种UI的地址,需要的可以去看看: H-ui:http://www.h-ui.net/H-ui.admin.shtml ,是一个前端大牛弄得,模仿bootstrap,做适合中国网上的UI. Ama

  • ASP.NET Mvc开发之EF延迟加载

    先来看看定义 EF延迟加载:就是使用Lamabda表达式或者Linq 从 EF实体对象中查询数据时,EF并不是直接将数据查询出来,而是在用到具体数据的时候才会加载到内存. 一.实体对象的Where方法返回一个什么对象? 大家来看一下上一篇文章的代码来分析一下: #region 查询文章列表+ActionResult Article() /// <summary> /// 查询文章列表 /// </summary> /// <returns></returns>

  • 初识ASP.NET Mvc5+EF7的奇妙之旅

    话说今年微软是很给力的,Win10算是吸引了大众的眼球了,而最新的.NET5框架更是OK. 最新的.NET5进行了开源,同时利用NuGet以及Node和Bower进行了跨平台化:这意味这可以直接在Mac或者Linux上使用.NET进行开发. 而最新的Mvc5和EF框架也算是进行了换脸了,跟之前Mvc4的项目都不一样,如果进行移植除了核心代码可以拷贝过来,其他的统统要重新来过. 最近准备改版一下网站,所以尝试了一把最新的框架:当然由于现在还是预览版所以改动什么的都超大,所以也走了不少弯路:特在此记

  • ASP.NET MVC+EF框架+EasyUI实现权限管系列

    前言:本文开始我们便一步一步的来实现这个权限系统的初步设计-框架搭建,首先我要说的是我们需要开发工具Visual Studio 2012或者10也行,其次是我们要有SQL Server数据库,如果是Visual Studio 2010的话,你还要安装MVC4的开发文件,这个是吗?我不记得了,谁可以回答我一下的,我一直用2012,都是集成好的,所以不太清楚.因为这篇博客比较简单,只是建立一个简单的架构,所以我顺便进行一下MVC的知识补充,后面我也会这样穿插着介绍项目中遇到的技术,下面开始今天之旅.

  • ASP.NET MVC5+EF6+EasyUI 后台管理系统(81)-数据筛选(万能查询)实例

    前言 听标题的名字似乎是一个非常牛X复杂的功能,但是实际上它确实是非常复杂的,我们本节将演示如何实现对数据,进行组合查询(数据筛选) 我们都知道Excel中是如何筛选数据的.就像下面一样 他是一个并的关系,我们现在要做的也是这样的效果,下面我们将利用EasyUI的DataGrid为例来扩展(就算是其他组件也是可以的,同样的实现方式!) 实现思路 1.前台通过查询组合json 2.后台通过反射拆解json 3.进行组合查询 虽然短短3点,够你写个3天天夜了 优点:需要从很多数据中得到精准的数据,通

  • ASP.NET MVC4+EF5+EasyUI+Unity2.x注入的后台管理系统之前端页面框架构建源码分享

    开始,我们有了一系列的解决方案,我们将动手搭建新系统吧. 用户的体验已经需要越来越注重,这次我们是左右分栏,左边是系统菜单,右边是一个以tabs页组成的页面集合,每一个tab都可以单独刷新和关闭,因为他们会是一个iframe 工欲善其事必先利其器.需要用到以下工具. Visual Studio 2012 您可以安装MVC4 for vs2010用VS2010来开发,但是貌似你将不能使用EF5.0将会是EF4.4版本,但这没有多大的关系. MVC4将挂载在.NET Framework4.5上. 好

随机推荐