Entity Framework使用Code First模式管理存儲(chǔ)過程
在EF中使用存儲(chǔ)過程和使用視圖是很相似的,一般會(huì)使用Database對(duì)象上的兩個(gè)方法:SqlQuery和ExecuteSqlCommand。為了從存儲(chǔ)過程中讀取很多數(shù)據(jù)行,我們只需要定義一個(gè)類,我們會(huì)將檢索到的所有數(shù)據(jù)行物質(zhì)化到該類實(shí)例的集合中。比如,從下面的存儲(chǔ)過程讀取數(shù)據(jù):
CREATE PROCEDURE [dbo].[SelectBooks] @BookTypeName AS NVARCHAR(10) AS BEGIN select B.Name,B.Author,B.PublicationDate,T.BookTypeName from Books as B join BookTypes as T on B.BookTypeId=T.BookTypeId where T.BookTypeName=@BookTypeName END
1、定義實(shí)體類
Book實(shí)體類定義如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeFirstProcedureApp.Model
{
public class Book
{
public int Id { get; set; }
public string Name { get; set; }
public string Author { get; set; }
public DateTime PublicationDate { get; set; }
public virtual BookType BookType { get; set; }
}
}BookType實(shí)體類定義如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeFirstProcedureApp.Model
{
public class BookType
{
public BookType()
{
Books = new HashSet<Book>();
}
public int BookTypeId { get; set; }
public string BookTypeName { get; set; }
public virtual ICollection<Book> Books { get; set; }
}
}2、定義與存儲(chǔ)過程結(jié)果匹配的實(shí)體類
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeFirstProcedureApp.Model
{
public class BookFromProcedure
{
public string Name { get; set; }
public string Author { get; set; }
public DateTime PublicationDate { get; set; }
public string BookTypeName { get; set; }
}
}注意:類的屬性名必須和存儲(chǔ)過程中定義的列名一致。
3、創(chuàng)建種子初始化器類
using CodeFirstProcedureApp.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeFirstProcedureApp.EF
{
public class Initializer : DropCreateDatabaseIfModelChanges<EFDbContext>
{
protected override void Seed(EFDbContext context)
{
// 創(chuàng)建初始化數(shù)據(jù)
BookType bookType = new BookType()
{
BookTypeName = "文學(xué)小說",
Books = new List<Book>
{
new Book(){Name="人間失格",Author="太宰治",PublicationDate=DateTime.Parse("2015-08-01")},
new Book(){Name="解憂雜貨店",Author="東野圭吾",PublicationDate=DateTime.Parse("2014-05-01")},
new Book(){Name="追風(fēng)箏的人",Author="卡勒德胡賽尼",PublicationDate=DateTime.Parse("2006-08-01")},
new Book(){Name="百年孤獨(dú)",Author="加西亞馬爾克斯",PublicationDate=DateTime.Parse("2011-06-01")},
new Book(){Name="霍亂時(shí)期的愛情",Author="加西亞馬爾克斯",PublicationDate=DateTime.Parse("2015-06-01")}
}
};
BookType bookType2 = new BookType()
{
BookTypeName = "科學(xué)",
Books = new List<Book>
{
new Book(){Name="人類簡史",Author="尤瓦爾赫拉利",PublicationDate=DateTime.Parse("2017-01-01")}
}
};
context.BookTypes.Add(bookType);
context.BookTypes.Add(bookType2);
base.Seed(context);
}
}
}4、定義數(shù)據(jù)上下文類
using CodeFirstProcedureApp.Model;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CodeFirstProcedureApp.EF
{
public class EFDbContext :DbContext
{
public EFDbContext()
: base("name=AppConnection")
{
Database.SetInitializer(new Initializer());
}
// 添加到數(shù)據(jù)上下文中
public DbSet<Book> Books { get; set; }
public DbSet<BookType> BookTypes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// 配置表名和主鍵
modelBuilder.Entity<Book>().ToTable("Books").HasKey(p => p.Id);
modelBuilder.Entity<BookType>().ToTable("BookTypes").HasKey(p => p.BookTypeId);
// 設(shè)置實(shí)體關(guān)系
// BookType和 Books 一對(duì)多關(guān)系 外鍵:BookTypeId
modelBuilder.Entity<BookType>().HasMany(p => p.Books).WithRequired(t => t.BookType)
.Map(m =>
{
m.MapKey("BookTypeId");
});
base.OnModelCreating(modelBuilder);
}
}
}5、運(yùn)行程序
使用SQL語句創(chuàng)建存儲(chǔ)過程:
var createSql = @"CREATE PROCEDURE [dbo].[SelectBooks]
@BookTypeName AS NVARCHAR(10)
AS
BEGIN
select B.Name,B.Author,B.PublicationDate,T.BookTypeName from Books as B
join BookTypes as T on B.BookTypeId=T.BookTypeId where T.BookTypeName=@BookTypeName
END";
context.Database.ExecuteSqlCommand(createSql);查看數(shù)據(jù)庫:

調(diào)用存儲(chǔ)過程查詢數(shù)據(jù)
注意:在使用存儲(chǔ)過程前,先要在存儲(chǔ)過程中執(zhí)行該存儲(chǔ)過程或者使用上面的程序生成存儲(chǔ)過程。
var sql = "SelectBooks {0}";
var books = context.Database.SqlQuery<BookFromProcedure>(sql, "文學(xué)小說");
books.ToList().ForEach(p =>
{
Console.WriteLine("BookName:" + p.Name + " Author:" + p.Author + " BookTypeName:" + p.BookTypeName + " PublicationDate:" + p.PublicationDate);
});在上面的代碼中,我們制定了使用哪個(gè)類讀取查詢的結(jié)果,創(chuàng)建SQL語句時(shí),也為存儲(chǔ)過程的參數(shù)提供了一個(gè)格式化占位符,調(diào)用SqlQuery時(shí)為那個(gè)參數(shù)提供了一個(gè)值。假如要提供多個(gè)參數(shù)的話,多個(gè)格式化占位符必須要用逗號(hào)分隔,還要給SqlQuery提供值的數(shù)組。我們也可以使用表值函數(shù)代替存儲(chǔ)過程。存儲(chǔ)過程執(zhí)行結(jié)果如下:

6、執(zhí)行無返回值的存儲(chǔ)過程
另一個(gè)用例就是假如存儲(chǔ)過程沒有任何的返回值,只是對(duì)數(shù)據(jù)庫中的一張表或者多張表執(zhí)行了一條命令的情況。一個(gè)存儲(chǔ)過程做了多少事情不重要,重要的是它不返回任何數(shù)據(jù)。例如:下面的存儲(chǔ)過程只是更新了一些數(shù)據(jù):
CREATE PROCEDURE UpdateBooks @name AS NVARCHAR(60), @id as int AS BEGIN UPDATE Books SET Name=@name WHERE Id=@id END
先在數(shù)據(jù)庫中執(zhí)行該存儲(chǔ)過程,然后要調(diào)用該存儲(chǔ)過程,我們使用ExecuteSqlCommand()方法。該方法會(huì)返回存儲(chǔ)過程或者其它任何SQL語句受影響的行數(shù)。如果對(duì)這個(gè)返回值不感興趣,可以忽略返回值。
var sql = "UpdateBooks @name,@id";
SqlParameter[] para = new SqlParameter[]
{
new SqlParameter("@id",1d),
new SqlParameter("@name","人間失敗"),
};
var book = context.Books.Where(p => p.Id == 1);
Console.WriteLine("執(zhí)行存儲(chǔ)過程前的數(shù)據(jù)為:");
foreach (var item in book)
{
Console.WriteLine(item.Name + "\t" + item.Author + "\t" + item.PublicationDate);
}
var rowsAffected = context.Database.ExecuteSqlCommand(sql, para);
Console.WriteLine("影響的行數(shù)為{0}條", rowsAffected);
Console.WriteLine("執(zhí)行存儲(chǔ)過程之后的數(shù)據(jù)為:");
var books = context.Books.Where(p => p.Id == 1);
foreach (var item in books)
{
Console.WriteLine(item.Name + "\t" + item.Author + "\t" + item.PublicationDate);
}上面的代碼中為存儲(chǔ)過程提供了兩個(gè)參數(shù):一個(gè)是Name,一個(gè)是Id。這里需要注意的是:我們必須嚴(yán)格按照它們?cè)诖鎯?chǔ)過程中定義的順序依次傳入相應(yīng)的值,它們會(huì)以參數(shù)數(shù)組傳入ExecuteSqlCommand。執(zhí)行結(jié)果如下:

很大程度上,EF降低了存儲(chǔ)過程的需要。然而,仍舊有很多原因要使用它們。這些原因包括安全標(biāo)準(zhǔn)、遺留數(shù)據(jù)庫或者效率問題。比如,如果需要在單個(gè)操作中更新幾千條數(shù)據(jù),然后在通過EF檢索出來;如果每次都更新一行,然后在保存那些實(shí)例,效率是很低的。最后,即使使用了SqlQuery()方法調(diào)用了存儲(chǔ)過程,也可以更新數(shù)據(jù)。
注意:開發(fā)者可以執(zhí)行任意的SQL語句,只需要將上面SqlQuery或ExecuteSqlCommand方法中的存儲(chǔ)過程名稱改為要執(zhí)行的SQL語句就可以了。
示例代碼下載地址:點(diǎn)此下載
到此這篇關(guān)于Entity Framework使用Code First模式管理存儲(chǔ)過程的文章就介紹到這了。希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Entity?Framework代碼優(yōu)先(Code?First)模式
- Entity Framework使用Code First模式管理事務(wù)
- Entity Framework使用Code First模式管理視圖
- Entity?Framework使用Code?First的實(shí)體繼承模式
- Entity Framework使用Code First模式管理數(shù)據(jù)庫
- EF使用Code First模式生成單數(shù)形式表名
- EF使用Code First模式給實(shí)體類添加復(fù)合主鍵
- 使用EF的Code?First模式操作數(shù)據(jù)庫
- C#筆記之EF Code First 數(shù)據(jù)模型 數(shù)據(jù)遷移
- Entity?Framework代碼優(yōu)先Code?First入門
相關(guān)文章
.NET Core/Framework如何創(chuàng)建委托大幅度提高反射調(diào)用的性能詳解
反射是一種很重要的技術(shù),下面這篇文章主要給大家介紹了關(guān)于.NET Core/Framework如何創(chuàng)建委托大幅度提高反射調(diào)用性能的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2018-09-09
ASP.NET?Core中間件實(shí)現(xiàn)限流的代碼
這篇文章主要介紹了ASP.NET?Core中間件實(shí)現(xiàn)限流的方法,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
給Repeater控件里添加序號(hào)的5種才常見方法介紹
Repeater是我們經(jīng)常用的一個(gè)顯示數(shù)據(jù)集的數(shù)據(jù)控件那么我們?cè)撛趺礊镽epeater控件添加序號(hào)呢?下面編輯為大家介紹幾種常用的為Repeater控件添加序號(hào)的方法2013-09-09
深入Lumisoft.NET實(shí)現(xiàn)郵件發(fā)送功能的方法詳解
本篇文章對(duì)使用Lumisoft.NET實(shí)現(xiàn)郵件發(fā)送功能的方法機(jī)型了詳細(xì)的分析介紹。需要的朋友參考下2013-05-05

