存储过程

存储过程一直存在于任何一种关系型数据库中,如微软的SQL Server.存储过程是包含在数据库中的一些代码,通常为数据执行一些操作,它能为数据密集型计算提高性能,也能执行一些为业务逻辑. 当你使用数据的时候,有时你会通过存储过程来获取它们.

在本章, 我们探讨一些EF在使用存储过程时,需要关注的地方。我们在本书的其它章节也使用了存储过程, 但通常都是context为执行插入、更新和删除动作。

在本章,我们将为你展示多种使用存储过程的方式。

10-1. 非Code Frist方式返回一个实体集合

问题

想用非Code Frist方式从存储过程里取得一个实体集合

解决方案

Code second (我把它译为非Code Frist)是参照 Code-First 技术,为一个已经存在的数据库建模的方式

我们假设有一个 POCO模型,如Listing 10-1所示:

Listing 10-1. The Customer POCO Model

public class Customer

{

public int CustomerId { get; set; }

public string Name { get; set; }

public string Company { get; set; }

public string ContactTitle { get; set; }

}

我们已经设置好了DbContext子类和Customer 实体集,如Listing 10-2所示:

Listing 10-2. The DbContext Subclass for Customer Entities

public class EF6RecipesContext : DbContext

{

public DbSet<Customer> Customers { get; set; }

public EF6RecipesContext() : base("name=EF6CodeFirstRecipesContext")

{

}

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

base.OnModelCreating(modelBuilder);

modelBuilder.Types<Customer>()

.Configure(c =>

{

c.HasKey(cust => cust.CustomerId);

c.Property(cust => cust.CustomerId)

.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

c.Property(cust => cust.Name)

.HasMaxLength(50);

c.Property(cust => cust.Company)

.HasMaxLength(50);

c.Property(cust => cust.ContactTitle)

.HasMaxLength(50);

c.ToTable("Customer", "Chapter10");

});

}

}

在数据库中,我们已经定义了如Listing 10-3所示的存储过程,该存储过程根据公司名称和客户标题返回符合条件的 customer

Listing 10-3. GetCustomers Returns All of the Customers with the Given Title in the Given Company.

create procedure Chapter10.GetCustomers

(@Company varchar(50),@ContactTitle varchar(50))

as

begin

select * from

chapter10.Customer where

(@Company is null or Company = @Company) and

(@ContactTitle is null or ContactTitle = @ContactTitle)

End

为了在方法中使用  GetCustomers 存储过程,操作如下:

1. 在DbContext 子类中创建一个公开的方法(命名为GetCustomers),它接受两个string参数,并返回Customer集合, 如 Listing 10-4所示.

Listing 10-4. A New Method to Return a Collection of Customer Objects

public ICollection<Customer> GetCustomers(string company, string contactTitle)

{

throw new NotImplementedException();

}

2.接下来实现这个GetCustomers() 方法,它调用DbContext.Database的SqlQuery方法DbContext.Database

如Listing 10-5所示.

Listing 10-5. DbContext Subclass with GetCustomers() Implementation

public class EF6RecipesContext : DbContext

{

public DbSet<Customer> Customers { get; set; }

public EF6RecipesContext() : base("name=EF6CodeFirstRecipesContext")

{

}

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

base.OnModelCreating(modelBuilder);

modelBuilder.Types<Customer>()

.Configure(c =>

{

c.HasKey(cust => cust.CustomerId);

c.Property(cust => cust.CustomerId)

.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

c.Property(cust => cust.Name)

.HasMaxLength(50);

c.Property(cust => cust.Company)

.HasMaxLength(50);

c.Property(cust => cust.ContactTitle)

.HasMaxLength(50);

c.ToTable("Customer", "Chapter10");

});

}

public ICollection<Customer> GetCustomers(string company, string contactTitle)

{

return Database.SqlQuery<Customer>( "EXEC Chapter10.GetCustomers @Company,

@ContactTitle"

, new SqlParameter("Company", company)

, new SqlParameter("ContactTitle", contactTitle))

.ToList();

}

}

3.接下来的这个代码段Listing 10-6 就是调用GetCustomers存储过程.

Listing 10-6. Querying the Model with the GetCustomers Stored Procedure via the GetCustomers()

Method

//插入一些Customer,让存储过程查询.

using (var context = new EF6RecipesContext())

{

var c1 = new Customer {Name = "Robin Steele", Company = "GoShopNow.com",

ContactTitle="CEO"};

var c2 = new Customer {Name = "Orin Torrey", Company = "GoShopNow.com",

ContactTitle="Sales Manager"};

var c3 = new Customer {Name = "Robert Lancaster", Company = "GoShopNow.com",

ContactTitle = "Sales Manager"};

var c4 = new Customer { Name = "Julie Stevens", Company = "GoShopNow.com",

ContactTitle = "Sales Manager" };

context.Customers.Add(c1);

context.Customers.Add(c2);

context.Customers.Add(c3);

context.Customers.Add(c4);

context.SaveChanges();

}

using (var context = new EF6RecipesContext())

{

var allCustomers = context.GetCustomers("GoShopNow.com", "Sales Manager");

Console.WriteLine("Customers that are Sales Managers at GoShopNow.com");

foreach (var c in allCustomers)

{

Console.WriteLine("Customer: {0}", c.Name);

}

}

以下Listing 10-6是控制台输出结果:

============================================================================================

Customers that are Sales Managers at GoShopNow.com

Customer: Orin Torrey

Customer: Robert Lancaster

Customer: Julie Stevens

=============================================================

它是如何工作的?

为了能接收数据库中的存储过程里返回的实体集合,我们在DbContext子类中实现了 GetCustomers()方法,该方法用DbContext.Database.SqlQuery<T>() 来执行存储过程 GetCustomers(它的定义见Listing 10-3). SqlQuery() 方法能用来执行返回一个结果集的 DML(数据操纵语言)语句. 该方法接收一个SQL语句的字符串。SqlQuery<T>() 泛型方法返回一个开发人员指定的强类型的实体集。

附:创建示例用到的数据库的脚本文件

Entity Framework 6 Recipes 2nd Edition(10-1)译->非Code Frist方式返回一个实体集合的更多相关文章

  1. Entity Framework 6 Recipes 2nd Edition 译 -> 目录 -持续更新

    因为看了<Entity Framework 6 Recipes 2nd Edition>这本书前面8章的翻译,感谢china_fucan. 从第九章开始,我是边看边译的,没有通读,加之英语 ...

  2. Entity Framework 6 Recipes 2nd Edition(9-1)译->用Web Api更新单独分离的实体

    第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...

  3. Entity Framework 6 Recipes 2nd Edition(9-3)译->找出Web API中发生了什么变化

    9-3. 找出Web API中发生了什么变化 问题 想通过基于REST的Web API服务对数据库进行插入,删除和修改对象图,而不必为每个实体类编写单独的更新方法. 此外, 用EF6的Code Fri ...

  4. Entity Framework 6 Recipes 2nd Edition(9-4)译->Web API 的客户端实现修改跟踪

    9-4. Web API 的客户端实现修改跟踪 问题 我们想通过客户端更新实体类,调用基于REST的Web API 服务实现把一个对象图的插入.删除和修改等数据库操作.此外, 我们想通过EF6的Cod ...

  5. Entity Framework 6 Recipes 2nd Edition(13-4)译 -> 有效地创建一个搜索查询

    问题 你想用LINQ写一个搜索查询,能被转换成更有效率的SQL.另外,你想用EF的CodeFirst方式实现. 解决方案 假设你有如下Figure 13-6所示的模型 Figure 13-6. A s ...

  6. Entity Framework 6 Recipes 2nd Edition(13-2)译 -> 用实体键获取一个单独的实体

    问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Paint ...

  7. Entity Framework 6 Recipes 2nd Edition(13-3)译 -> 为一个只读的访问获取实体

    问题 你想有效地获取只是用来显示不会更新的操作的实体.另外,你想用CodeFirst的方式来实现 解决方案 一个非常常见行为,尤其是网站,就是只是让用户浏览数据.大多数情况下,用户不会更新数据.在这种 ...

  8. Entity Framework 6 Recipes 2nd Edition(13-5)译 -> 使POCO的修改追踪更高

    问题 你正在使用POCO,你想提高修改跟踪的性能,同时使内存消耗更少.另外,你想通过EF的CodeFirst方式来实现. 解决方案 假设你有一个关于Account(帐户)和相关的Payments(支付 ...

  9. Entity Framework 6 Recipes 2nd Edition(13-8)译 -> 把昂贵的属性移到其它实体

    问题 你想把一个昂贵的属性移到另一个实体,这样你就可以延迟加载当前这个实体.对于一个加载昂贵的而且很少用到的属性尤其有用. 解决方案 模型和上一节(Recipes 13-7)的一致,如Figure13 ...

随机推荐

  1. 旺财速啃H5框架之Bootstrap(四)

    上一篇<<旺财速啃H5框架之Bootstrap(三)>>已经把导航做了,接下来搭建内容框架.... 对于不规整的网页,要做成自适应就有点玩大了.... 例如下面这种版式的页面. ...

  2. 使用ServiceStack构建Web服务

    提到构建WebService服务,大家肯定第一个想到的是使用WCF,因为简单快捷嘛.首先要说明的是,本人对WCF不太了解,但是想快速建立一个WebService,于是看到了MSDN上的这一篇文章 Bu ...

  3. Socket聊天程序——Common

    写在前面: 上一篇记录了Socket聊天程序的客户端设计,为了记录的完整性,这里还是将Socket聊天的最后一个模块--Common模块记录一下.Common的设计如下: 功能说明: Common模块 ...

  4. ubuntu如何安装nodejs最新版 本

    如何正确的安装nodejs? 我们可以先安装nvm, git clone https://github.com/creationix/nvm.git ~/.nvm 然后打开 ~/.bashrc ,   ...

  5. geotrellis使用(二十八)栅格数据色彩渲染(多波段真彩色)

    目录 前言 实现过程 总结 一.前言        上一篇文章介绍了如何使用Geotrellis渲染单波段的栅格数据,已然很是头疼,这几天不懈努力之后工作又进了一步,整清楚了如何使用Geotrelli ...

  6. 集合(set)-Python3

    set 的 remove() 和 discard()  方法介绍. 函数/方法名   等价操作符 说明 所有集合类型 len(s)   集合基数:集合s中元素个数 set([obj])   可变集合工 ...

  7. 第12章 Linux系统管理

    1. 进程管理 1.1 进程查看 (1)进程简介 进程是正在执行的一个程序或命令(如ls命令也是一个进程),每个进程都是一个运行的实体,都有自己的地址空间,并占用一定的系统资源. (2)进程管理的作用 ...

  8. Xamarin.Android之ActionBar与菜单

    一.选项卡 如今很多应用都会使用碎片以便在同一个活动中能够显示多个不同的视图.在Android 3.0 以上的版本中,我们已经可以使用ActionBar提供的Tab来实现这种效果,而不需要我们自己去实 ...

  9. Angular2笔记:NgModule

    Angular的模块的目的是用来组织app的逻辑结构. 在ng中使用@NgModule修饰的class就被认为是一个ng module.NgModule可以管理模块内部的Components.Dire ...

  10. MVVM大比拼之knockout.js源码精析

    简介 本文主要对源码和内部机制做较深如的分析,基础部分请参阅官网文档. knockout.js (以下简称 ko )是最早将 MVVM 引入到前端的重要功臣之一.目前版本已更新到 3 .相比同类主要有 ...