咱們已經知道EF能夠將L2E或Entity SQL的查詢語句自動轉換成SQL命令,也能夠根據實體的狀態自動生成Insert/update/delete的Sql命令。這節介紹EF中使用預先定義的存儲過程對一張或者多種表進行CURD操做。html
EF API會新建一個function來映射數據庫中的自定義函數或存儲過程。下邊講解EF DbFirst模式下存儲過程的用法,EF CodeFirst存儲過程的用法會在之後的EF CodeFirst系列中介紹。數據庫
首先在數據庫建立一個名爲GetCoursesByStudentId的存儲過程,這個存儲過程返回一個學生的全部課程。瀏覽器
CREATE PROCEDURE [dbo].[GetCoursesByStudentId] -- Add the parameters for the stored procedure here @StudentId int = null AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; -- Insert statements for procedure here select c.courseid, c.coursename,c.Location, c.TeacherId from student s left outer join studentcourse sc on sc.studentid = s.studentid left outer join course c on c.courseid = sc.courseid where s.studentid = @StudentId END
這一步和普通生成EMD過程是同樣的,值得注意的是在Choose Your Database Objects and Settings這一步勾選咱們新建的存儲過程(GetCoursesByStudentId)和下邊的Import selected stored procedures and functions into the entity model ,以下圖所示app
GetCoursesByStudentId()返回Course實體集合,因此咱們不須要返回一個新的複雜類型。右鍵Function Imports下的GetCoursesByStudentId方法,選擇Edit,出現如下界面,把Entities設置爲Course便可函數
經過上邊兩步,在context中會生成一個GetCoursesByStudentId方法:post
如今咱們就能夠愉快地使用context.GetCoursesByStudentId來執行存儲過程了!以下:spa
using (var context = new SchoolDBEntities()) { var courses = context.GetCoursesByStudentId(1); foreach (Course cs in courses) Console.WriteLine(cs.CourseName); }
在數據庫中執行的命令爲: exec [dbo].[GetCoursesByStudentId] @StudentId=1 設計
一點補充:EF中的表值函數和查詢的存儲過程使用的步驟是如出一轍的(表值函數和存儲過程原本就很相似,一個最重要的區別是EF中表值函數的返回值可用linq查詢過濾)3d
這一部分介紹怎麼經過存儲過程來執行CUD(creat,update,delete)操做。code
咱們在數據庫添加如下幾個存儲:
Sp_InsertStudentInfo(添加):
CREATE PROCEDURE [dbo].[sp_InsertStudentInfo] -- Add the parameters for the stored procedure here @StandardId int = null, @StudentName varchar(50) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; INSERT INTO [SchoolDB].[dbo].[Student]([StudentName],[StandardId]) VALUES(@StudentName, @StandardId) SELECT SCOPE_IDENTITY() AS StudentId END
sp_UpdateStudent(修改):
CREATE PROCEDURE [dbo].[sp_UpdateStudent] -- Add the parameters for the stored procedure here @StudentId int, @StandardId int = null, @StudentName varchar(50) AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; Update [SchoolDB].[dbo].[Student] set StudentName = @StudentName,StandardId = @StandardId where StudentID = @StudentId; END
sp_DeleteStudent(刪除):
CREATE PROCEDURE [dbo].[sp_DeleteStudent] -- Add the parameters for the stored procedure here @StudentId int AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. SET NOCOUNT ON; DELETE FROM [dbo].[Student] where StudentID = @StudentId END
首先咱們要升級EDM把這些存儲過程添加當咱們的EDM中。右鍵設計器,選擇Update Model from Database,就出現了升級界面,以下圖所示,展開Stored Procedure and Functions,勾選咱們上邊建立的三個存儲過程,而後點擊Finish。
這時模型瀏覽器中在Store Model中有了這三個存儲過程,可是Function Imports中沒有,以下所示:
打開模型設計器在Student實體上右鍵,選擇Stored Procedure Mapping,來打開映射詳情界面,以下圖
在下面的映射詳細界面,咱們看到<Select Insert Function>, <Select Update Function>, and <Select Delete Function>,給這些下拉菜單分別選擇對應的存儲過程,同時選擇存儲過程的輸入輸出參數,以下圖所示:
右擊Student實體,選擇Validate,確保沒有錯誤
如今咱們執行add,update,或者delete時,EF再也不執行自動生成的SQL命令,而是經過這些存儲過程來執行,下面是一個栗子:
using (var context = new SchoolDBEntities()) { Student student = new Student() { StudentName = "New student using SP"}; context.Students.Add(student); //執行 sp_InsertStudentInfo context.SaveChanges(); student.StudentName = "Edit student using SP"; //執行 sp_UpdateStudent context.SaveChanges(); context.Students.Remove(student); //執行 sp_DeleteStudentInfo context.SaveChanges(); }
調用SaveChange()方法時,在數據庫中執行的命令以下:
exec [dbo].[sp_InsertStudentInfo] @StandardId=NULL,@StudentName='New student using SP' go exec [dbo].[sp_UpdateStudent] @StudentId=47,@StandardId=NULL,@StudentName='Edit student using SP' go exec [dbo].[sp_DeleteStudent] @StudentId=47 go
注意:不管是使用存儲過程仍是默認生成的Sql命令,當插入一條記錄並執行完SaveChange()方法後,這個新的實例會當即分配一個Id。這樣設計是爲了有效地追蹤實體,讓咱們能夠對實體執行進一步的操做(如沒有id執行update會拋出異常),以下圖:
EF系列目錄連接:Entity Franmework系列教程彙總