要專業系統地學習EF前往《你必須掌握的Entity Framework 6.x與Core 2.0》這本書的作者(汪鵬,Jeffcky)的博客:https://www.cnblogs.com/CreateMyself/
前面說到EF中的原始查詢,就是寫SQL語句執行
那么還有存儲過程的調用也是通過那幾個方法來的
調用查詢數據的存儲過程使用:ctx.Database.SqlQuery<T>() 或者 ctx.DbSet<T>.SqlQuery()
調用Insert、Update、Delete操作的存儲過程使用:ExceuteSqlCommand()或者ExceuteSqlCommandAsync()
調用存儲過程
我們先手動地添加一個存儲過程:select * from tb_products

create procedure GetProducts as begin set nocount on; select * from tb_Products; set nocount off; end go
緊接着調用它,可以

var res = ctx.Database.SqlQuery<Product>("dbo.GetProducts"); Console.WriteLine(JsonConvert.SerializeObject(res,set));
然后再創建一個存儲過程:select id,name from tb_products

create procedure GetProducts2 as begin select id,[name] from tb_Products end go
接收類型的屬性數量和返回數據集的字段數量不一致,報錯。得自己另外定義類型去接收

var res = ctx.Database.SqlQuery<Product>("dbo.getproducts2"); Console.WriteLine(JsonConvert.SerializeObject(res)); // 未經處理的異常: System.Data.Entity.Core.EntityCommandExecutionException: The data reader is incompatible with the specified 'CodeFirstNamespace.Product'. A member of the type, 'Price', does not have a corresponding column in the data reader with the same name.
來看看帶參數的存儲過程,在方法中該怎么寫

-- 傳遞參數,name create procedure GetProductsByName ( @name as nvarchar(50) ) as begin select *from tb_Products where [Name] =@name; end go -- 執行 exec GetProductsByName '磚頭' go

// 一個參數name var parameter = new SqlParameter("@name","水泥"); var res = ctx.Database.SqlQuery<Product>("dbo.getproductsByName @name",parameter); Console.WriteLine(JsonConvert.SerializeObject(res)); // [{"Order":null,"Name":"水泥","Price":50.00,"Unit":"袋","FK_Order_Id":"469b82be-8139-4e67-b566-5b2b5f6d838d","Id":"d951e96d-a581-4f87-a567-bedb4c24eca3","AddTime":"2019-01-15T10:28:00.653"}]
來看看多個參數的存儲過程

-- 兩個參數,id,price create procedure GetProducts3 ( @id as nvarchar(36), @price as decimal(18,2) ) as begin select * from tb_Products where id =@id and Price = @price end go

// 兩個參數 var parameterList = new List<SqlParameter> { new SqlParameter(){ ParameterName="@id",SqlDbType = System.Data.SqlDbType.NVarChar,Value ="6495f22b-f1ef-4bd2-b81e-c49eaf6e2f21"}, new SqlParameter(){ ParameterName="@price",SqlDbType=System.Data.SqlDbType.Decimal,Value=5} }; var parameterArr = parameterList.ToArray(); var res = ctx.Database.SqlQuery<Product>("dbo.getproducts3 @id,@price",parameterArr); Console.WriteLine(JsonConvert.SerializeObject(res)); //[{"Order":null,"Name":"蘋果","Price":5.00,"Unit":"斤","FK_Order_Id":"e18757db-1db8-4f7f-b702-79138709b304","Id":"6495f22b-f1ef-4bd2-b81e-c49eaf6e2f21","AddTime":"2019-01-15T10:35:03.36"}] // 簡直沒有問題
上面的都是執行的查詢操作,來看看添加操作的存儲過程,我們使用ExcuteSqlCommand()方法

-- 添加數據 create procedure AddProduct ( @name as nvarchar(50), @price as decimal(18,2), @unit as nvarchar(10) ) as begin insert into tb_Products values(newid(),@name,@price,'469b82be-8139-4e67-b566-5b2b5f6d838d',getdate(),@unit) end go

var parameterList = new List<SqlParameter> { new SqlParameter(){ ParameterName="@name",SqlDbType = System.Data.SqlDbType.NVarChar,Value ="花生"}, new SqlParameter(){ ParameterName="@price",SqlDbType = System.Data.SqlDbType.Decimal,Value = 4.4}, new SqlParameter(){ ParameterName ="@unit",SqlDbType = System.Data.SqlDbType.NVarChar,Value="斤"} }; var paraArr = parameterList.ToArray(); var res = ctx.Database.ExecuteSqlCommand("dbo.addproduct @name,@price,@unit", paraArr); Console.WriteLine(res); // result : 1
EF自動生成存儲過程
上面的存儲過程都是手動添加,現在我們在OnModelCreating方法中寫配置,讓它自動添加存儲過程

modelBuilder.Entity<Order>().MapToStoredProcedures();
這樣他會給你生成三個存儲過程

public partial class jinshantest4 : DbMigration { public override void Up() { CreateStoredProcedure( "dbo.Order_Insert", p => new { Id = p.String(maxLength: 128), OrderNO = p.String(), Description = p.String(), AddTime = p.DateTime(), }, body: @"INSERT [dbo].[tb_Orders]([Id], [OrderNO], [Description], [AddTime]) VALUES (@Id, @OrderNO, @Description, @AddTime)" ); CreateStoredProcedure( "dbo.Order_Update", p => new { Id = p.String(maxLength: 128), OrderNO = p.String(), Description = p.String(), AddTime = p.DateTime(), }, body: @"UPDATE [dbo].[tb_Orders] SET [OrderNO] = @OrderNO, [Description] = @Description, [AddTime] = @AddTime WHERE ([Id] = @Id)" ); CreateStoredProcedure( "dbo.Order_Delete", p => new { Id = p.String(maxLength: 128), }, body: @"DELETE [dbo].[tb_Orders] WHERE ([Id] = @Id)" ); } public override void Down() { DropStoredProcedure("dbo.Order_Delete"); DropStoredProcedure("dbo.Order_Update"); DropStoredProcedure("dbo.addOrder"); } }
也可以對它進行詳細配置,比如我指定insert存儲過程的名稱為“orderAdd”

modelBuilder.Entity<Order>().MapToStoredProcedures(x => x.Insert(a => a.HasName("addOrder")));
跟新后,可以看到存儲過程都添加 成功了
最后來調用一個EF為我們創建的存儲過程

// 添加一個訂單 var parameterList = new List<SqlParameter> { new SqlParameter{ ParameterName="@Id",SqlDbType = System.Data.SqlDbType.NVarChar,Value = Guid.NewGuid().ToString()}, new SqlParameter{ ParameterName="@OrderNO",SqlDbType = System.Data.SqlDbType.NVarChar,Value ="order435435"}, new SqlParameter{ ParameterName="@Description",SqlDbType = System.Data.SqlDbType.NVarChar,Value="description4364537ryrtey"}, new SqlParameter{ ParameterName="@AddTime",SqlDbType = System.Data.SqlDbType.DateTime,Value =DateTime.Now} }; var paraArr = parameterList.ToArray(); var res = ctx.Database.ExecuteSqlCommand("dbo.addOrder @Id,@OrderNO,@Description,@AddTime",paraArr); Console.WriteLine(res); // result:1
可以的