10-9. 在多对多关系中为插入和删除使用存储过程

问题

想要在一个无载荷的多对多关系中使用存储过程(存储过程只影响关系的连接表)

解决方案

假设有一个多对多关系的作者( Author)表和书籍( Book)表. 用连接表AuthorBook来做多对多关系,如 Figure 10-11.所示:

Figure 10-11. A payload-free, many-to-many relationship between an Author and a Book

当把表生成模型,那么模型就如Figure 10-12所示:

Figure 10-12. The model created by importing the tables in Figure 10-11

接下来用存储过程创建插入和删除操作:

1.在数据库中,创建如Listing 10-23所示的存储过程.

Listing 10-23. The stored Procedures for the Insert and Delete Actions

create procedure [chapter10].[InsertAuthorBook]

(@AuthorId int,@BookId int)

as

begin

insert into chapter10.AuthorBook(AuthorId,BookId) values (@AuthorId,@BookId)

end

go

create procedure [chapter10].[DeleteAuthorBook]

(@AuthorId int,@BookId int)

as

begin

delete chapter10.AuthorBook where AuthorId = @AuthorId and BookId = @BookId

end

2. 右击模型设计视图,选择“从数据库中更新模型”,选择 Listing 10-23所创建的存储过程,单击“完成”,这样就把存储过程添加到了模型里。

3. 目前版本的EF没有为一个关系插入和删除操作映射的设计视图,只能用手工去映射, 右击.edmx 文件,选择“打开方式”,选择“XML (文本)编辑器”. 在<AssociationSetMapping> 标签下插入 Listing 10-24所示的代码(译注:根据自己的例子命名修改代码里的)

Listing 10-24. Mapping the Stored Procedures to the Insert and Delete Actions for the Many-to-Many Association

<ModificationFunctionMapping>

<InsertFunction FunctionName="EFRecipesModel1009.Store.InsertAuthorBook">

<EndProperty Name="Author">

<ScalarProperty Name="AuthorId" ParameterName="AuthorId" />

</EndProperty>

<EndProperty Name="Book">

<ScalarProperty Name="BookId" ParameterName="BookId" />

</EndProperty>

</InsertFunction>

<DeleteFunction FunctionName="EFRecipesModel1009.Store.DeleteAuthorBook">

<EndProperty Name="Author">

<ScalarProperty Name="AuthorId" ParameterName="AuthorId" />

</EndProperty>

<EndProperty Name="Book">

<ScalarProperty Name="BookId" ParameterName="BookId" />

</EndProperty>

</DeleteFunction>

</ModificationFunctionMapping>

接下来Listing 10-25 代码演示了插入和删除操作.你可以用Sql Profiler来查看当

InsertAuthorBook 和DeleteAuthorBook 存储过程被EF在更新多对多关系时调用后生成的SQL语句

Listing 10-25. Inserting into the Model

class Program

{

static void Main(string[] args)

{

using (var context = new EFRecipesEntities1009())

{

context.Database.ExecuteSqlCommand("delete from chapter10.AuthorBook");

context.Database.ExecuteSqlCommand("delete from chapter10.book");

context.Database.ExecuteSqlCommand("delete from chapter10.Author");

var auth1 = new Author { Name = "Jane Austin" };

var book1 = new Book

{

Title = "Pride and Prejudice",

ISBN = "1848373104"

};

var book2 = new Book

{

Title = "Sense and Sensibility",

ISBN = "1440469563"

};

auth1.Books.Add(book1);

auth1.Books.Add(book2);

var auth2 = new Author { Name = "Audrey Niffenegger" };

var book3 = new Book

{

Title = "The Time Traveler's Wife",

ISBN = "015602943X"

};

auth2.Books.Add(book3);

context.Authors.Add(auth1);

context.Authors.Add(auth2);

context.SaveChanges();

context.Books.Remove(book1);

context.SaveChanges();

}

Console.WriteLine("\npress any key to exit...");

Console.ReadKey();

}

}

SQL Profiler里跟踪到的SQL语句如下(Listing 10-25)所示:

exec sp_executesql N'insert [Chapter10].[Author]([Name])values (@0)

select [AuthorId] from [Chapter10].[Author]

where @@ROWCOUNT > 0 and [AuthorId] = scope_identity()',N'@0 varchar(50)',@0='Jane Austin'

exec sp_executesql N'insert [Chapter10].[Author]([Name])values (@0)

select [AuthorId] from [Chapter10].[Author]

where @@ROWCOUNT > 0 and [AuthorId] = scope_identity()',N'@0 varchar(50)',

@0='Audrey Niffenegger'

exec sp_executesql N'insert [Chapter10].[Book]([Title], [ISBN])values (@0, @1)

select [BookId]    from [Chapter10].[Book]

where @@ROWCOUNT > 0 and [BookId] = scope_identity()',N'@0 varchar(50),

@1 varchar(50)',@0='Pride and Prejudice',@1='1848373104'

exec sp_executesql N'insert [Chapter10].[Book]([Title], [ISBN])values (@0, @1)

select [BookId] from [Chapter10].[Book]

where @@ROWCOUNT > 0 and [BookId] = scope_identity()',N'@0 varchar(50),

@1 varchar(50)',@0='Sense and Sensibility',@1='1440469563'

exec sp_executesql N'insert [Chapter10].[Book]([Title], [ISBN])values (@0, @1)

select [BookId]  from [Chapter10].[Book]

where @@ROWCOUNT > 0 and [BookId] = scope_identity()',N'@0 varchar(50),

@1 varchar(50)',@0='The Time Traveler''s Wife',@1='015602943X'

exec [Chapter10].[InsertAuthorBook] @AuthorId=1,@BookId=1

exec [Chapter10].[InsertAuthorBook] @AuthorId=1,@BookId=2

exec [Chapter10].[InsertAuthorBook] @AuthorId=2,@BookId=3

exec [Chapter10].[DeleteAuthorBook] @AuthorId=1,@BookId=1

exec sp_executesql N'delete [Chapter10].[Book] where ([BookId] = @0)',N'@0 int',@0=1

它是如何工作的?

为把存储过程映射到多对多关系中的插入和删除操作, 我们在数据库中创建存储过程,然后用存储过程模型.由于EF设计视图不支持关系型的模型映射插入和删除操作,我们需要用XML编辑器直接打开.edmx 文件, 在Mappings 节点里 <ModificationFunctionMapping> 标签下,我们添加了插入和删除操作映射到存储过程的代码。

从Listing 10-25跟踪生成的SQL,我们可以看到,不只是插入或删除 Author 和 Book 两个表, 同时我们也可以看到,存储过程在关系模型中插入和删除操作时被使用。

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

Entity Framework 6 Recipes 2nd Edition(10-9)译 -> 在多对多关系中为插入和删除使用存储过程的更多相关文章

  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-9)译 -> 避免Include

    问题 你想不用Include()方法,立即加载一下相关的集合,并想通过EF的CodeFirst方式实现. 解决方案 假设你有一个如Figure 13-14所示的模型: Figure 13-14. A ...

随机推荐

  1. Be Better:遇见更好的自己-2016年记

    其实并不能找到好的词语来形容过去的一年,感觉就如此平淡的过了!没有了毕业的稚气,看事情淡了,少了一丝浮躁,多了一分认真.2016也许就是那句话-多读书,多看报,少吃零食多睡觉,而我更愿意说--Be B ...

  2. Android UI体验之全屏沉浸式透明状态栏效果

    前言: Android 4.4之后谷歌提供了沉浸式全屏体验, 在沉浸式全屏模式下, 状态栏. 虚拟按键动态隐藏, 应用可以使用完整的屏幕空间, 按照 Google 的说法, 给用户一种 身临其境 的体 ...

  3. ExtJS 4.2 业务开发(二)数据展示和查询

    本篇开始模拟一个船舶管理系统,提供查询.添加.修改船舶的功能,这里介绍其中的数据展示和查询功能. 目录 1. 数据展示 2. 数据查询 3. 在线演示 1. 数据展示 在这里我们将模拟一个船舶管理系统 ...

  4. Kooboo CMS技术文档之二:Kooboo CMS的安装步骤

    在IIS上安装Kooboo CMS Kooboo CMS安装之后 安装的常见问题 1. 在IIS上安装Kooboo CMS Kooboo CMS部署到正式环境相当简单,安装过程是一个普通MVC站点在I ...

  5. 个人网站对xss跨站脚本攻击(重点是富文本编辑器情况)和sql注入攻击的防范

    昨天本博客受到了xss跨站脚本注入攻击,3分钟攻陷--其实攻击者进攻的手法很简单,没啥技术含量.只能感叹自己之前竟然完全没防范. 这是数据库里留下的一些记录.最后那人弄了一个无限循环弹出框的脚本,估计 ...

  6. java中易错点(二)

    java,exe是java虚拟机 javadoc.exe用来制作java文档 jdb.exe是java的调试器 javaprof,exe是剖析工具 解析一: sleep是线程类(Thread)的方法, ...

  7. ABP领域层

    1.实体Entites 1.1 概念 实体是DDD(领域驱动设计)的核心概念之一. 实体是具有唯一标识的ID且存储在数据库总.实体通常被映射成数据库中的一个表. 在ABP中,实体继承自Entity类. ...

  8. js 基础篇(点击事件轮播图的实现)

    轮播图在以后的应用中还是比较常见的,不需要多少行代码就能实现.但是在只掌握了js基础知识的情况下,怎么来用较少的而且逻辑又简单的方法来实现呢?下面来分析下几种不同的做法: 1.利用位移的方法来实现 首 ...

  9. Linux基础介绍【第五篇】

    linux权限位 Linux文件或目录的权限位是由9个权限位来控制,每三位为一组,它们分别是文件属主权限.属组权限.其他用户权限. r:read可读权限,对应数字4: w:write可写权限,对应数字 ...

  10. Linux C语言解析并显示.bmp格式图片

    /************************* *bmp.h文件 *************************/ #ifndef __BMP_H__ #define __BMP_H__ # ...