MVC 5在Visual Basic - Async中的EF 6和具有实体框架的存储过程

本教程是一系列12中的第九,它教导您如何使用实体框架进行数据访问和Visual Basic构建MVC 5应用程序。在早期的教程中,您学习了如何使用同步编程模型读取和更新数据。在本教程中,您可以看到如何实现异步编程模型。异步代码可以帮助应用程序执行更好,因为它更好地使用服务器资源。

在本教程中,您还可以了解如何在实体上使用存储过程,更新和删除操作。最后,您将重新将应用程序重新运到Windows Azure,以及您从部署第一次实现的数据库更改。

原辅导系列,由汤姆Dykstra生产 里克安德森 ( @rickandmsft. )使用C#语言编写。我的版本尽可能靠近原件,只改变编码语言。叙述文本从原始文本保持不变,并与Microsoft权限一起使用。

本教程系列教授如何使用实体框架6创建ASP.NET MVC 5应用程序 Visual Studio 2013 Express for web。该系列使用代码第一工作流程。有关如何在代码第一,数据库首先选择的信息的信息,请参阅 实体框架开发工作流程.

教程系列总共包括12个部分。它们旨在顺序顺序排列,因为每个部分都在上一节中赋予的知识。通过这些部分的进步反映在Visual Studio Express for Web项目下载,该部分伴随着具有您通过该系列构建的Web应用程序的每个部分。

下载代码

可用本节的代码 这里。拯救 。压缩 文件到方便的位置,然后提取内容。确保您安装了一个版本的Visual Studio 2013(Express for Web,Professional,Premium或Ultimate),然后双击 .sln. 文件。项目在IDE中打开后,按 Shift + Ctrl + B 建立解决方案。这将确保从Nuget恢复所有包,并且可能需要一段时间根据您的互联网连接速度。

通过该系列的导航路径如下:

  1. 创建实体框架数据模型
  2. 实施基本的CRUD功能
  3. 排序,过滤和分页
  4. 连接弹性和命令拦截
  5. 代码首次迁移和部署
  6. 创建更复杂的数据模型
  7. 阅读相关数据
  8. 更新相关数据
  9. 异步和存储过程
  10. 处理并发
  11. 实现 - 继承
  12. 高级实体框架方案

为什么要与异步代码打扰?

Web服务器的可用线程数有限,并且在高负载情况下,所有可用的线程都可能正在使用。发生这种情况时,服务器无法处理新请求,直到线程被释放。通过同步代码,许多线程可能被捆绑在于它们实际上没有做任何工作,因为他们正在等待I / O完成。利用异步代码,当一个进程等待I / O完成时,它的线程被释放为服务器用于处理其他请求。因此,异步代码使得可以更有效地使用服务器资源,并且服务器已启用以处理更多的流量而无需延迟。

在早期版本的.NET中,写入和测试异步代码复杂,容易出错,难以调试。在.NET 4.5中,写入,测试和调试异步代码非常容易,您通常应该写异步代码,除非您没有理由不。异步代码确实引入了少量开销,但对于低流量情况,性能击中可忽略不计,而对于高流量情况,潜在的性能改善是大幅的。

有关异步编程的更多信息,请参阅 使用.NET 4.5的异步支持以避免阻止呼叫.

创建部门控制器

以与前面的控制器相同的方式创建部门控制器,除了这次选择 使用异步控制器 actions check box.

MVC5与EF6.

以下高光显示如何添加到索引方法的同步代码中以使其异步:

异步 Function 在 dex() As Task(Of ActionResult)
    Dim departments = db.Departments.Include(Function(d) d.Administrator)
    Return View(等待 部门.Tolist.异步())
End Function

应用了四种更改以使实体框架数据库查询能够异步执行:

  • 该方法标有 异步 关键字,告诉编译器为方法主体的部分生成回调,并自动创建 任务(ActionResult) 返回的对象。
  • 返回类型从ActionResult更改为 任务(ActionResult) . The Task(Of T) 类型表示具有类型的结果的持续工作 T.
  • 这 等待 关键字应用于Web服务调用。当编译器看到此关键字时,它在场景后面将该方法分为两部分。第一部分以异步启动的操作结束。第二部分被置于操作完成时调用的回调方法。
  • 异步版本的 tol 调用扩展方法。

为什么是 部门.Tolist. 声明修改但不是 部门= db.departments. 陈述?原因是只有原因,原因是异步地执行要发送到数据库的查询或命令的语句。这 部门= db.departments. 语句设置查询,但未执行查询直到 tol 调用方法。因此,只有 tol 方法异步执行。

在里面 细节 method and the httpget编辑 and 删除 methods, the  方法是导致查询发送到数据库的方法,以便这是异步执行的方法:

异步 Function 细节(ByVal id As Integer?) As Task(Of ActionResult)
    If IsNothing(id) 这n
        Return New HttpStatusCodeResult(HttpStatusCode.BadRequest)
    End If
    Dim department As 部门 = 等待 db.Departments.找Async(id)
    If IsNothing(department) 这n
        Return HttpNotFound()
    End If
    Return View(department)
End Function

在里面 创造 , httppost编辑, 和 deleteconfirmed methods, it is the 保存更改 方法调用导致执行命令,而不是诸如此类的语句 db.departments.add(部门) 其中仅导致要修改内存中的实体。

异步 Function 创造(<Bind(Include := "DepartmentID,Name,Budget,StartDate,InstructorID")> ByVal department As 部门) As Task(Of ActionResult)
    If ModelState.IsValid 这n
        db.departments.add(部门)
        等待 db.SaveChanges异步()
        Return RedirectToAction("Index")
    End If 

打开 视图\部门\ index.vbhtml,并用以下代码替换模板代码:

@ModelType IEnumerable(Of ContosoUniversity.Models.部门)
@Code
    ViewBag.Title = "Departments"
End Code

<h2>部门s</h2>

<p>
    @Html.ActionLink("Create New", "Create")
</p>
<table class="table">
    <tr>
        <th>
            @Html.DisplayNameFor(Function(model) model.Name)
        </th>
        <th>
            @Html.DisplayNameFor(Function(model) model.Budget)
        </th>
        <th>
            @Html.DisplayNameFor(Function(model) model.StartDate)
        </th>
        <th>
            行政人员
        </th>
        <th></th>
    </tr>

@For Each item Model
    @<tr>
        <td>
            @Html.DisplayFor(Function(modelItem) item.Name)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) item.Budget)
        </td>
        <td>
            @Html.DisplayFor(Function(modelItem) item.StartDate)
        </td>
        <td>
             @Html.DisplayFor(Function(modelItem) item.Administrator.FullName)
        </td>
        <td>
            @Html.ActionLink("Edit", "Edit", New With {.id = item.DepartmentID }) |
            @Html.ActionLink("Details", "Details", New With {.id = item.DepartmentID }) |
            @Html.ActionLink("Delete", "Delete", New With {.id = item.DepartmentID })
        </td>
    </tr>
Next

</table>

此代码将标题从索引更改为Departments,将管理员名称移动到右侧,并提供管理员的全名。

在里面 创造, 删除, 细节, 和 编辑 视图,更改教学字段的标题"Administrator"更改部门名称字段的方式相同"Department"在课程中。 

运行应用程序,然后单击 部门s tab.

MVC5与EF6. 

一切都与其他控制器相同,但在该控制器中,所有SQL查询都是异步执行的。

当您使用具有实体框架的异步编程时要注意的一些事情:

  • 异步代码不是线程安全的。换句话说,不要尝试使用相同的上下文实例并行执行多个操作。
  • 如果要利用异步代码的性能优势,请确保您使用的任何库包(例如用于分页),如果它们调用任何导致查询发送到的任何实体框架方法,也会使用异步。数据库。

使用存储过程来插入,更新和删除

一些开发人员和DBA更喜欢使用存储的数据库访问程序。在早期版本的实体框架中,您可以使用存储过程检索数据 执行原始SQL查询,但您无法指示EF使用存储过程进行更新操作。在EF 6中,您可以首先配置代码以使用存储过程。

  1. 在  dal \ schoolcontext.vb.,将突出显示的代码添加到 onmodelcreating. method.

    Protected Overrides Sub onmodelcreating.(ByVal modelBuilder As DbModelBuilder)
        modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)()
        modelBuilder.Entity(Of Course)() _
            .HasMany(Function(c) c.Instructors).WithMany(Function(i) i.Courses) _
            .Map(Function(t) t.MapLeftKey("CourseID") _
            .MapRightKey("InstructorID") _
            .ToTable("CourseInstructor"))
        modelBuilder.Entity(Of 部门)().MapToStoredProcedures()
    End Sub
    此代码指示实体框架在部门实体上使用存储过程中的存储过程,更新和删除操作。
  2. 在包管理控制台中,输入以下命令:

    add-migration DepartmentSP

    打开 迁移\<timestamp>_DepartmentSP.vb 查看代码 向上 创建插入,更新和删除存储过程的方法:

    Public Overrides Sub 向上()
        创造StoredProcedure(
            "dbo.Department_Insert",
            Function(p) New With
                {
                    .Name = p.String(maxLength:=50),
                    .Budget = p.Decimal(precision:=19, scale:=4, storeType:="money"),
                    .StartDate = p.DateTime(),
                    .InstructorID = p.Int()
                },
            body:=
                "INSERT [dbo].[Department]([Name], [Budget], [StartDate], [InstructorID])" & vbCrLf & _
                "VALUES (@Name, @Budget, @StartDate, @InstructorID)" & vbCrLf & _
                "" & vbCrLf & _
                "DECLARE @DepartmentID int" & vbCrLf & _
                "SELECT @DepartmentID = [DepartmentID]" & vbCrLf & _
                "FROM [dbo].[Department]" & vbCrLf & _
                "WHERE @@ROWCOUNT > 0 AND [DepartmentID] = scope_identity()" & vbCrLf & _
                "" & vbCrLf & _
                "SELECT t0.[DepartmentID]" & vbCrLf & _
                "FROM [dbo].[Department] AS t0" & vbCrLf & _
                "WHERE @@ROWCOUNT > 0 AND t0.[DepartmentID] = @DepartmentID"
        )
    
        创造StoredProcedure(
            "dbo.Department_Update",
            Function(p) New With
                {
                    .DepartmentID = p.Int(),
                    .Name = p.String(maxLength:=50),
                    .Budget = p.Decimal(precision:=19, scale:=4, storeType:="money"),
                    .StartDate = p.DateTime(),
                    .InstructorID = p.Int()
                },
            body:=
                "UPDATE [dbo].[Department]" & vbCrLf & _
                "SET [Name] = @Name, [Budget] = @Budget, [StartDate] = @StartDate, [InstructorID] = @InstructorID" & vbCrLf & _
                "WHERE ([DepartmentID] = @DepartmentID)"
        )
    
        创造StoredProcedure(
            "dbo.Department_Delete",
            Function(p) New With
                {
                    .DepartmentID = p.Int()
                },
            body:=
                "DELETE [dbo].[Department]" & vbCrLf & _
                "WHERE ([DepartmentID] = @DepartmentID)"
        )
    
    End Sub
  3. 在包管理控制台中,输入以下命令:

    update-database
  4. 在调试模式下运行应用程序,单击“ 部门s tab, and then click 创建新的.

  5. 输入新部门的数据,然后单击 创造.

    MVC5与EF6.
  6. 在Visual Studio中,查看日志 输出 窗口查看存储过程用于插入新部门行。

    MVC5与EF6.

代码首先创建默认存储的过程名称。如果您使用的是现有数据库,则可能需要自定义存储的过程名称才能使用数据库中已定义的存储过程。有关如何执行此操作的信息,请参阅 实体框架代码首先插入/更新/删除存储过程 .

如果要自定义生成的存储过程,可以编辑迁移的脚手架代码 向上 创建存储过程的方法。这样,只要运行迁移,就会反映出更改,并且当部署后在生产中自动运行时,将应用于您的生产数据库。

如果要更改以前迁移中创建的现有存储过程,则可以使用 添加迁移 命令生成空白迁移,然后手动编写调用的代码 AlterstoredProcedure method.

部署到Windows Azure

本节要求您完成可选的 将应用部署到Windows Azure 章节迁移和部署 本系列的教程。如果您迁移了通过删除本地项目中的数据库解决的错误,请跳过本节。

  1. 在Visual Studio中,右键单击该项目 解决方案资源管理器 and select 发布 从上下文菜单中。

  2. 点击 发布.

    Visual Studio将应用程序部署到Windows Azure,应用程序在默认浏览器中打开,在Windows Azure中运行。

  3. 测试应用程序以验证它的工作。

    您第一次运行访问数据库的页面,实体框架运行所有迁移upmethod,所需的所有迁移upmethod都会使用当前数据模型使数据库更新。您现在可以使用自上次部署的自从您的上次部署之后添加的所有网页,包括在本教程中添加的部门页面。

概括

在本教程中,您了解如何通过编写异步执行的代码来提高服务器效率,以及如何使用存储,更新和删除操作的存储过程。在里面 下一个教程,您将看到如何在多个用户尝试同时编辑相同的记录时,如何防止数据丢失。