Entity Framework 6提供支持存储过程的新特性,本文具体演示Entity Framework 6 Code First的存储过程操作。

Code First的插入/修改/删除存储过程

  默认情况下下,Code First配置对全部实体的插入/修改/删除操作均直接针对表进行。从EF6开始可以配置对全部或部分实体来选择使用存储过程。

1. 基本实体映射

1.1 通过Fluent API,配置使用插入/修改/删除存储过程

modelBuilder
.Entity<Blog>()
.MapToStoredProcedures();

1.2 Code First在数据库中生成存储过程的约定

  ◊ 生成三个存储过程,名称分别为<type_name>_Insert, <type_name>_Update, <type_name>_Delete

  ◊ 参数名对应于属性名 (注意:如果在 property上使用 HasColumnName() 或者 Column attribute 来重命名,那么参数也将使用这个重命名过的名称 );

  ◊ The insert stored procedure 为每一个属性都有一个参数,除了那些标记为数据库产生的(identity or computed),返回结果为那些标记为数据库产生的属性列;

  ◊ The update stored procedure 为每一个属性都有一个参数,除了那些标记为数据库产生且模式为 computed 的。一些并发标记的需要一个代表原始值的参数。返回值为那些 computed property 的列;

  ◊ The delete stored procedure 参数为实体主键(或者组合主键),此外也需要为每一个独立关联的外键准备一个参数(指那些没有在实体上定义相应外键属性的关系),一些并发标记的需要一个代表原始值的参数。

  示例:

  实体文件blog.cs:

using System;
using System.Collections.Generic; namespace EF6.Models
{
public partial class Blog
{
public int BlogID { get; set; }
public string Name { get; set; }
public string Url { get; set; }
}
}

  实体映射文件BlogMap.cs:

using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration; namespace EF6.Models.Mapping
{
public class BlogMap : EntityTypeConfiguration<Blog>
{
public BlogMap()
{
// Primary Key
this.HasKey(t => t.BlogID); // Properties
this.Property(t => t.Name)
.HasMaxLength(); this.Property(t => t.Url)
.HasMaxLength(); // Table & Column Mappings
this.ToTable("Blog");
this.Property(t => t.BlogID).HasColumnName("BlogID");
this.Property(t => t.Name).HasColumnName("Name");
this.Property(t => t.Url).HasColumnName("Url"); // Procedures
this.MapToStoredProcedures();
}
}
}

  在程序包管理器控制台中依次执行:

PM> Enable-Migrations -EnableAutomaticMigrations
PM> Add-Migration InitialCreate
PM> Update-Database -Verbose

  执行完成之后生成数据库:

  监控生成数据的SQL语句:

CREATE TABLE [dbo].[Blog] (
[BlogID] [int] NOT NULL IDENTITY,
[Name] [nvarchar](50),
[Url] [nvarchar](100),
CONSTRAINT [PK_dbo.Blog] PRIMARY KEY ([BlogID])
CREATE PROCEDURE [dbo].[Blog_Insert]
@Name [nvarchar](50),
@Url [nvarchar](100)
AS
BEGIN
INSERT [dbo].[Blog]([Name], [Url])
VALUES (@Name, @Url) DECLARE @BlogID int
SELECT @BlogID = [BlogID]
FROM [dbo].[Blog]
WHERE @@ROWCOUNT > 0 AND [BlogID] = scope_identity() SELECT t0.[BlogID]
FROM [dbo].[Blog] AS t0
WHERE @@ROWCOUNT > 0 AND t0.[BlogID] = @BlogID
END
CREATE PROCEDURE [dbo].[Blog_Update]
@BlogID [int],
@Name [nvarchar](50),
@Url [nvarchar](100)
AS
BEGIN
UPDATE [dbo].[Blog]
SET [Name] = @Name, [Url] = @Url
WHERE ([BlogID] = @BlogID)
END
CREATE PROCEDURE [dbo].[Blog_Delete]
@BlogID [int]
AS
BEGIN
DELETE [dbo].[Blog]
WHERE ([BlogID] = @BlogID)
END

  2、重新默认约定

  2.1、重命名存储过程名称

modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("Modify_Blog")));
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("Update_Blog"))
.Delete(d => d.HasName("Delete_Blog"))
.Insert(i => i.HasName("Insert_Bblog")));
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
{
s.Update(u => u.HasName("Update_Blog"));
s.Delete(d => d.HasName("Delete_Blog"));
s.Insert(i => i.HasName("Insert_Blog"));
});
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration; namespace EF6.Models.Mapping
{
public class BlogMap : EntityTypeConfiguration<Blog>
{
public BlogMap()
{
// Primary Key
this.HasKey(t => t.BlogID); // Properties
this.Property(t => t.Name)
.HasMaxLength(); this.Property(t => t.Url)
.HasMaxLength(); // Table & Column Mappings
this.ToTable("Blog");
this.Property(t => t.BlogID).HasColumnName("BlogID");
this.Property(t => t.Name).HasColumnName("Name");
this.Property(t => t.Url).HasColumnName("Url"); // Procedures
this.MapToStoredProcedures(s =>{
s.Insert(u => u.HasName("Insert_Blog"));
s.Update(u => u.HasName("Update_Blog"));
s.Delete(u => u.HasName("Delete_Blog"));
});
}
}
}

  运行之后执行的SQL语句:

EXECUTE sp_rename @objname = N'dbo.Blog_Insert', @newname = N'Insert_Blog', @objtype = N'OBJECT'
EXECUTE sp_rename @objname = N'dbo.Blog_Update', @newname = N'Update_Blog', @objtype = N'OBJECT'
EXECUTE sp_rename @objname = N'dbo.Blog_Delete', @newname = N'Delete_Blog', @objtype = N'OBJECT'

  2.2、重命名存储过程参数名称

modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.Parameter(b => b.BlogID, "Blog_ID")));
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration; namespace EF6.Models.Mapping
{
public class BlogMap : EntityTypeConfiguration<Blog>
{
public BlogMap()
{
// Primary Key
this.HasKey(t => t.BlogID); // Properties
this.Property(t => t.Name)
.HasMaxLength(); this.Property(t => t.Url)
.HasMaxLength(); // Table & Column Mappings
this.ToTable("Blog");
this.Property(t => t.BlogID).HasColumnName("BlogID");
this.Property(t => t.Name).HasColumnName("Name");
this.Property(t => t.Url).HasColumnName("Url"); // Procedures
this.MapToStoredProcedures(s =>
{
s.Update(u => u.Parameter(b => b.BlogID, "Blog_ID"));
});
}
}
}

  运行之后执行的SQL语句:

ALTER PROCEDURE [dbo].[Blog_Update]
@Blog_ID [int],
@Name [nvarchar](50),
@Url [nvarchar](100)
AS
BEGIN
UPDATE [dbo].[Blog]
SET [Name] = @Name, [Url] = @Url
WHERE ([BlogID] = @Blog_ID)
END
modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Update(u => u.HasName("Update_Blog")
.Parameter(b => b.BlogID, "Blog_ID")
.Parameter(b => b.Name, "Blog_Name")
.Parameter(b => b.Url, "Blog_Url"))
.Delete(d => d.HasName("Delete_Blog")
.Parameter(b => b.BlogID, "Blog_ID"))
.Insert(i => i.HasName("Insert_Blog")
.Parameter(b => b.Name, "Blog_Name")
.Parameter(b => b.Url, "Blog_Url")));

  2.3、重命名数据库自动生成列的返回值的列名

modelBuilder
.Entity<Blog>()
.MapToStoredProcedures(s =>
s.Insert(i => i.Result(b => b.BlogID, "generated_blog_identity")));
using System.ComponentModel.DataAnnotations.Schema;
using System.Data.Entity.ModelConfiguration; namespace EF6.Models.Mapping
{
public class BlogMap : EntityTypeConfiguration<Blog>
{
public BlogMap()
{
// Primary Key
this.HasKey(t => t.BlogID); // Properties
this.Property(t => t.Name)
.HasMaxLength(); this.Property(t => t.Url)
.HasMaxLength(); // Table & Column Mappings
this.ToTable("Blog");
this.Property(t => t.BlogID).HasColumnName("BlogID");
this.Property(t => t.Name).HasColumnName("Name");
this.Property(t => t.Url).HasColumnName("Url"); // Procedures
this.MapToStoredProcedures(s =>
{
s.Insert(i => i.Result(b => b.BlogID, "generated_blog_identity"));
});
}
}
}

  运行之后执行的SQL语句:

ALTER PROCEDURE [dbo].[Blog_Insert]
@Name [nvarchar](50),
@Url [nvarchar](100)
AS
BEGIN
INSERT [dbo].[Blog]([Name], [Url])
VALUES (@Name, @Url) DECLARE @BlogID int
SELECT @BlogID = [BlogID]
FROM [dbo].[Blog]
WHERE @@ROWCOUNT > 0 AND [BlogID] = scope_identity() SELECT t0.[BlogID] AS generated_blog_identity
FROM [dbo].[Blog] AS t0
WHERE @@ROWCOUNT > 0 AND t0.[BlogID] = @BlogID
END

  3、多对多关系

  两个多对多的实体类:

using System;
using System.Collections.Generic; namespace EF6.Models
{
public partial class Post
{
public int PostID { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public virtual ICollection<Tag> Tags { get; set; }
}
}
using System;
using System.Collections.Generic; namespace EF6.Models
{
public partial class Tag
{
public int TagID { get; set; }
public string TagName { get; set; }
public virtual ICollection<Post> Posts { get; set; }
}
}

  映射存储过程:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Post>()
.HasMany(p => p.Tags)
.WithMany(t => t.Posts)
.MapToStoredProcedures();
}

  默认生成的存储过程:

  ◊ 生成两个存储过程,命名为 <type_one><type_two>_Insert 和 <type_one><type_two>_Delete

  ◊ 参数为每一类型的主键(或组合主键),命名为 <type_name>_<property_name>

  代码运行后生成的存储过程:

CREATE PROCEDURE [dbo].[PostTag_Insert]
@Post_PostID [int],
@Tag_TagID [int]
AS
BEGIN
INSERT [dbo].[PostTags]([Post_PostID], [Tag_TagID])
VALUES (@Post_PostID, @Tag_TagID)
END
CREATE PROCEDURE [dbo].[PostTag_Delete]
@Post_PostID [int],
@Tag_TagID [int]
AS
BEGIN
DELETE [dbo].[PostTags]
WHERE (([Post_PostID] = @Post_PostID) AND ([Tag_TagID] = @Tag_TagID))
END

  参考资料:

  http://msdn.microsoft.com/en-us/data/dn468673

Entity Framework 6 Code First新特性:支持存储过程的更多相关文章

  1. Entity Framework Core 2.0 新特性

    本文翻译来自:https://docs.microsoft.com/en-us/ef/core/what-is-new/index 一.模型级查询过滤器(Model-level query filte ...

  2. 在Entity Framework 中用 Code First 创建新的数据库

    在Entity Framework 中用 Code First 创建新的数据库 (原文链接) 本文将逐步介绍怎样用Code First 创建新数据库,使用在代码中定义类和API中提供的特性(Attri ...

  3. AppBox升级进行时 - 拥抱Entity Framework的Code First开发模式

    AppBox 是基于 FineUI 的通用权限管理框架,包括用户管理.职称管理.部门管理.角色管理.角色权限管理等模块. 从Subsonic到Entity Framework Subsonic最早发布 ...

  4. Entity Framework 之 Code First

    使用NuGet助您玩转代码生成数据————Entity Framework 之 Code First [前言] 如果是Code First老鸟或者对Entity Framework不感兴趣,就不用浪费 ...

  5. 创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表

    创建ASP.NET Core MVC应用程序(3)-基于Entity Framework Core(Code First)创建MySQL数据库表 创建数据模型类(POCO类) 在Models文件夹下添 ...

  6. Entity Framework Core Code First 项目实践

    Entity Framework Core Code First 实践 任何一种技术的出现都是为了解决一系列特定的问题,只有了解了技术所要解决的关键问题,才能理解它的真正用途,之后,才能在实践中用好它 ...

  7. 【极力分享】[C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例【转载自https://segmentfault.com/a/1190000004152660】

      [C#/.NET]Entity Framework(EF) Code First 多对多关系的实体增,删,改,查操作全程详细示例 本文我们来学习一下在Entity Framework中使用Cont ...

  8. Entity Framework 第三篇 实体特性声明

    Entity Framework中对实体的特性声明有着严格的要求 1.实体必须要有主键特性,但是如果实体没有主键特性那怎么办? public int ExecuteSqlCommand(string ...

  9. MVC2、MVC3、MVC4、MVC5之间的区别 以及Entity Framework 6 Code First using MVC 5官方介绍教程

    现在MVC的技术日趋成熟,面对着不同版本的MVC大家不免有所迷惑 -- 它们之间有什么不同呢?下面我把我搜集的信息汇总一下,以便大家能更好的认识不同版本MVC的功能,也便于自己查阅. View Eng ...

随机推荐

  1. BZOJ4488: [Jsoi2015]最大公约数

    Description 给定一个长度为 N 的正整数序列Ai对于其任意一个连续的子序列{Al,Al+1...Ar},我们定义其权值W(L,R )为其长度与序列中所有元素的最大公约数的乘积,即W(L,R ...

  2. jsonp帮助你知道你关注的他或她喜欢什么歌曲

    利用腾讯提供的QQ音乐API,返回一段对方在QQ音乐收藏的歌曲名称json数据,并对该json做解析,就能知道你的那个他或她喜欢听什么歌曲了,然后你就知道他/她的品位了,然后就自己看着办了,嘿嘿.我只 ...

  3. mac 之 jmeter下载、解压、启动

    1:下载地址:http://jmeter.apache.org/download_jmeter.cgi 2:双击下载的zip文件,即可解压 3:打开终端,cd 到解压的目录下 例如:cd  /User ...

  4. 华清远见成为ARM大学计划正式合作伙伴

    来源:华清远见嵌入式学院 近日,华清远见教育集团成为ARM大学计划合作伙伴,这是ARM大学计划合作伙伴中的国内唯一教育机构.此次合作是ARM公司对华清远见教育集团的高度认可,也充分证明了华清远见这些年 ...

  5. #研发解决方案#分布式并行计算调度和管理系统Summoner

    郑昀 创建于2015/11/10 最后更新于2015/11/12 关键词:佣金计算.定时任务.数据抽取.数据清洗.数据计算.Java.Redis.MySQL.Zookeeper.azkaban2.oo ...

  6. 简单谈谈如何利用h5实现音频的播放

    作者:白狼 出处:http://www.manks.top/article/h5_audio本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律 ...

  7. apache+php 安装

    Apache和PHP的版本分别为: httpd-2.4.9-win64-VC11.zip php-5.6.9-Win32-VC11-x64.zip 下载地址: php-5.6.9-Win32-VC11 ...

  8. VS2010 中,windows服务不能添加 System.Web 引用

    今天在写windows服务的时候,右键添加引用->.NET中没有找到System.Web,在->Recent中找到System.Web,但添加完后却显示黄色叹号,最后百度一下解决了这个问题 ...

  9. 安卓中的Model-View-Presenter模式介绍

    转载自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0425/2782.html 英文原文:Introduction to M ...

  10. Linux tar文件打包

    tar格式,会打包成一个文件,可以对多个目录,或者多个文件进行打包 tar命令只是打包,不会压缩,打包前后大小是一样的 tar命令 -c    //打包 -x    //解压 -f    //指定文件 ...