总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理)

上一篇:EF学习笔记(八):更新关联数据

本篇原文:Async and Stored Procedures

为何要采用异步?

一个Web服务器肯定有可用线程的限制,那么在一些访问量特别大的情况下,线程肯定会消耗完;这个时候服务器肯定处理不了请求,必须等线程里处理结束才可以处理请求;

在非异步的时候,很多线程都处于等待状态,并不是一直在工作,而是在等类似于I/O等处理结束;

采用异步的时候,当一个处理在等待I/O处理结束的时候,可以先去做做其他事情;

所以异步处理可以使服务器更为高效,较低延迟的情况下处理更多的请求。

在早期的.NET中,写或者测试异步处理都是很复杂的,庆幸的是.NET 4.5以后写或者测试异步处理请求代码都非常简单,除非有特别的理由不采用异步处理;

异步处理确实会有一些多出来的系统开销,对于低流量的应用,效果可以忽略,但对于大流量的应用,效果是很明显的;

更专业的资料: Use .NET 4.5's async support to avoid blocking calls.

下面做些代码测试:

采用异步方式新建Department控制器:

自动生成的Index Action:

  public async Task<ActionResult> Index()
        {
            var departments = db.Departments.Include(d => d.Administrator);
            return View(await departments.ToListAsync());
        }

与非异步方式,有4处不同来实现EF异步请求数据:

1、请求方法加上了async标志关键字,等于告诉编译器这个方法中有部分方法体为异步的,需要生成针对部分方法体的异步回调,并且自动创建一个Task<ActionResult>对象作为异步返回;

2、返回类型从ActionResult变为Task<ActionResult>,Task<T>表明后续处理将使用T类型;

3、await关键字引用于Call Web Service,当编译器看到await这个关键字,就会把这个方法分为两部分,第1部分就是开始异步处理,第2部分就是异步处理完成后,再回调的部分;

4、采用ToList的异步版本方法;

(原文后面一段没看明白。。。感觉有些笔误以及思路没理清楚)

接后面改几个视图,把Index视图里稍微改下,显示Administrator的全名:

@model IEnumerable<EFTest.Models.Department>

@{
ViewBag.Title = "Departments";
} <h2>Departments</h2> <p>
@Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
@Html.DisplayNameFor(model => model.Name)
</th>
<th>
@Html.DisplayNameFor(model => model.Budget)
</th>
<th>
@Html.DisplayNameFor(model => model.StartDate)
</th>
<th>
Administrator
</th>
<th></th>
</tr> @foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.Name)
</td>
<td>
@Html.DisplayFor(modelItem => item.Budget)
</td>
<td>
@Html.DisplayFor(modelItem => item.StartDate)
</td>
<td>
@Html.DisplayFor(modelItem => item.Administrator.FullName)
</td>
<td>
@Html.ActionLink("Edit", "Edit", new { id=item.DepartmentID }) |
@Html.ActionLink("Details", "Details", new { id=item.DepartmentID }) |
@Html.ActionLink("Delete", "Delete", new { id=item.DepartmentID })
</td>
</tr>
} </table>

把Create\Edit视图中 InstructorID 字段标题 改为 Administrator ,把原来一行注释掉,增加一行:

     <div class="form-group">
<label class="control-label col-md-2" for="InstructorID">Administrator</label>
@*@Html.LabelFor(model => model.InstructorID, "InstructorID", htmlAttributes: new { @class = "control-label col-md-2" })*@
<div class="col-md-10">
@Html.DropDownList("InstructorID", null, htmlAttributes: new { @class = "form-control" })
@Html.ValidationMessageFor(model => model.InstructorID, "", new { @class = "text-danger" })
</div>
</div>
@model EFTest.Models.Department

@{
ViewBag.Title = "Delete";
} <h2>Delete</h2> <h3>Are you sure you want to delete this?</h3>
<div>
<h4>Department</h4>
<hr />
<dl class="dl-horizontal">
@*<dt>
@Html.DisplayNameFor(model => model.Administrator.LastName)
</dt> <dd>
@Html.DisplayFor(model => model.Administrator.LastName)
</dd>*@
<dt>
Administrator
</dt>
<dd>
@Html.DisplayFor(model => model.Administrator.FullName)
</dd>
<dt>
@Html.DisplayNameFor(model => model.Name)
</dt> <dd>
@Html.DisplayFor(model => model.Name)
</dd> <dt>
@Html.DisplayNameFor(model => model.Budget)
</dt> <dd>
@Html.DisplayFor(model => model.Budget)
</dd> <dt>
@Html.DisplayNameFor(model => model.StartDate)
</dt> <dd>
@Html.DisplayFor(model => model.StartDate)
</dd> </dl> @using (Html.BeginForm()) {
@Html.AntiForgeryToken() <div class="form-actions no-color">
<input type="submit" value="Delete" class="btn btn-default" /> |
@Html.ActionLink("Back to List", "Index")
</div>
}
</div>

Delete\Detail如上面修改方法;

效果:

看起来的效果和其他控制器一样。。。但这个控制器后台查询处理数据都是异步方式。

对于异步方式,有两点需要注意:

1、异步方式无法线程安全,换句话说,不要尝试同一个上下文实例来并行多次处理;

2、如果你要享受到异步方式的好处,记得所有使用到的并且涉及到数据库操作的类库(例如:分页)都需要采用异步方式;

采用存储过程来进行增删改

一些DBA比较推荐使用存储过程来进行数据操作,以前版本的EF只能通过存储过程取数据,更新数据做不到,而现在EF6就很简单可以实现;

把DAL文件夹中的SchoolContext.cs 中的OnModelCreating方法加入如下一行:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Entity<Course>()
.HasMany(c => c.Instructors).WithMany(i => i.Courses)
.Map(t => t.MapLeftKey("CourseID")
.MapRightKey("InstructorID")
.ToTable("CourseInstructor"));
modelBuilder.Entity<Department>().MapToStoredProcedures();
}

这样EF就会采用存储过程进行Department的操作;

首先先要数据库升级一下,建立好存储过程;在PMC中输入 add-migration DepartmentSP

然后在数据库迁移目录里就可以看到最新的日期时间戳的XXXXXXXXXXXXX_DepartmentSP.sc文件,打开这个文件就可以看到里面向数据库里增加了3个存储过程;

在PMC中输入update-database,执行完的结果,可以到数据库里查看:

有3个存储过程被产生;

其他代码都不用改动,在执行Department增删改的时候,EF会自动调用这个存储过程来进行。

现在采用的方式是EF Code First直接定义存储过程名的方式,如果要使用自己数据库中已有的存储过程,则参考:Entity Framework Code First Insert/Update/Delete Stored Procedures.

如果想自己定制存储过程的产生,可以在迁移中定义的up方法中来修改。

如果要改变一个已有的以前版本建立的存储过程,可以使用Add-Migration创建一个空的迁移,然后在一个叫AlterStoredProcedure方法中手动写代码;

EF学习笔记(九):异步处理和存储过程的更多相关文章

  1. EF学习笔记(十) 处理并发

    总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇:EF学习笔记(九):异步处理和存储过程 本篇原文链接:Handling Concurrency Concurrency ...

  2. EF学习笔记(十二):EF高级应用场景

    学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇链接:EF学习笔记(十一):实施继承 本篇原文链接:Advanced Entity Framework Scenari ...

  3. EF学习笔记(十一):实施继承

    学习总目录:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上篇链接:EF学习笔记(十) 处理并发 本篇原文链接:Implementing Inheritance 面向对象的世界里, ...

  4. EF学习笔记(八):更新关联数据

    学习笔记主目录链接:ASP.NET MVC5 及 EF6 学习笔记 - (目录整理) 上一篇链接:EF学习笔记(七):读取关联数据 本篇原文链接:Updating Related Data 本篇主要考 ...

  5. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  6. MDX导航结构层次:《Microsoft SQL Server 2008 MDX Step by Step》学习笔记九

    <Microsoft SQL Server 2008 MDX Step by Step>学习笔记九:导航结构层次   SQL Server 2008中SQL应用系列及BI笔记系列--目录索 ...

  7. python3.4学习笔记(九) Python GUI桌面应用开发工具选择

    python3.4学习笔记(九) Python GUI桌面应用开发工具选择 Python GUI开发工具选择 - WEB开发者http://www.admin10000.com/document/96 ...

  8. Go语言学习笔记九: 指针

    Go语言学习笔记九: 指针 指针的概念是当时学C语言时了解的.Go语言的指针感觉与C语言的没啥不同. 指针定义与使用 指针变量是保存内存地址的变量.其他变量保存的是数值,而指针变量保存的是内存地址.这 ...

  9. ASP.NET MVC 学习笔记-7.自定义配置信息 ASP.NET MVC 学习笔记-6.异步控制器 ASP.NET MVC 学习笔记-5.Controller与View的数据传递 ASP.NET MVC 学习笔记-4.ASP.NET MVC中Ajax的应用 ASP.NET MVC 学习笔记-3.面向对象设计原则

    ASP.NET MVC 学习笔记-7.自定义配置信息   ASP.NET程序中的web.config文件中,在appSettings这个配置节中能够保存一些配置,比如, 1 <appSettin ...

随机推荐

  1. 4. Go常量

    常量就是那些不可以改变的值 Go语言中定义常量的方式: const a = "admin" 则 a 就是一个常量,但实际上其后面的 "admin" 也是一个字符 ...

  2. PostgreSQL 锁等待诊断详解

    摘要PostgreSQL和大多数传统RDBMS一样,都设计了大量的锁来保证并发操作的数据一致性. 同时PG在设计锁等待时,以队列方式存储等待锁. 参考 ProcSleep()@src/backend/ ...

  3. Angularjs 动态创建属性

    循环输出 for (var i = 1; i < 7; i++) { var res='res'+i; $scope[res]=i; }

  4. 查看 设置mysql时区

    # 查看时区 show variables like '%time_zone%'; system_time_zone CST time_zone SYSTEM # 设置全局 set global ti ...

  5. CSRedisCore 在net core中的使用

    背景:与net core配套的StackExchange.Redis客户端总是间歇性的发生timeout异常. 由complexer单例对象创建的IDatabase对象,在产生Timeout异常后会导 ...

  6. dskinlite(uieasy mfc界面库)使用记录3:绘制动态元素(按钮控件通过隐藏方式修改图片显示)

    效果图: 分别是:正常,正常鼠标悬停,按下,按下鼠标悬停 XML代码: 75,76行定义了一个image,注意id和index属性 初始化代码: click代码: 147,148,153,154:通过 ...

  7. Maven [ERROR] 不再支持源选项 5。请使用 6 或更高版本

    报错信息如下 解决办法一 在settings.xml文件中指定jdk版本 既可以修改全局的settings.xml文件(C:\Program Files\apache-maven-3.6.0\conf ...

  8. vue生命周期-mounted和created的区别

    详情请查看:https://blog.csdn.net/xdnloveme/article/details/78035065 自己做个总结: beforeCreate 创建之前:已经完成了 初始化事件 ...

  9. WCF系列_WCF如何选择不同的绑定

    内容转载自<WCF核心技术> 开发者不用直接操作信道范型,而是由WCF根据服务OperationContract来选择合适的信道范型.大多数信道范型都有无会话两种变体.有会话信道会在客户端 ...

  10. liunx一键安装禅道

    一定要把压缩吧放在/opt下面,然后tar解压,启动 https://blog.csdn.net/sinat_23957257/article/details/82697458