存儲過程存儲過程一直存在於任何一種關係型資料庫中,如微軟的SQL Server.存儲過程是包含在資料庫中的一些代碼,通常為數據執行一些操作,它能為數據密集型計算提高性能,也能執行一些為業務邏輯. 當你使用數據的時候,有時你會通過存儲過程來獲取它們.在本章, 我們探討一些EF在使用存儲過程時,需要關註...
存儲過程
存儲過程一直存在於任何一種關係型資料庫中,如微軟的SQL Server.存儲過程是包含在資料庫中的一些代碼,通常為數據執行一些操作,它能為數據密集型計算提高性能,也能執行一些為業務邏輯. 當你使用數據的時候,有時你會通過存儲過程來獲取它們.
在本章, 我們探討一些EF在使用存儲過程時,需要關註的地方。我們在本書的其它章節也使用了存儲過程, 但通常都是context為執行插入、更新和刪除動作。
在本章,我們將為你展示多種使用存儲過程的方式。
10-1. 非Code Frist方式返回一個實體集合
問題
想用非Code Frist方式從存儲過程里取得一個實體集合
解決方案
Code second (我把它譯為非Code Frist)是參照 Code-First 技術,為一個已經存在的資料庫建模的方式
我們假設有一個 POCO模型,如Listing 10-1所示:
Listing 10-1. The Customer POCO Model
public class Customer
{
public int CustomerId { get; set; }
public string Name { get; set; }
public string Company { get; set; }
public string ContactTitle { get; set; }
}
我們已經設置好了DbContext子類和Customer 實體集,如Listing 10-2所示:
Listing 10-2. The DbContext Subclass for Customer Entities
public class EF6RecipesContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public EF6RecipesContext() : base("name=EF6CodeFirstRecipesContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Types<Customer>()
.Configure(c =>
{
c.HasKey(cust => cust.CustomerId);
c.Property(cust => cust.CustomerId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
c.Property(cust => cust.Name)
.HasMaxLength(50);
c.Property(cust => cust.Company)
.HasMaxLength(50);
c.Property(cust => cust.ContactTitle)
.HasMaxLength(50);
c.ToTable("Customer", "Chapter10");
});
}
}
在資料庫中,我們已經定義瞭如Listing 10-3所示的存儲過程,該存儲過程根據公司名稱和客戶標題返回符合條件的 customer
Listing 10-3. GetCustomers Returns All of the Customers with the Given Title in the Given Company.
create procedure Chapter10.GetCustomers
(@Company varchar(50),@ContactTitle varchar(50))
as
begin
select * from
chapter10.Customer where
(@Company is null or Company = @Company) and
(@ContactTitle is null or ContactTitle = @ContactTitle)
End
為了在方法中使用 GetCustomers 存儲過程,操作如下:
1. 在DbContext 子類中創建一個公開的方法(命名為GetCustomers),它接受兩個string參數,並返回Customer集合, 如 Listing 10-4所示.
Listing 10-4. A New Method to Return a Collection of Customer Objects
public ICollection<Customer> GetCustomers(string company, string contactTitle)
{
throw new NotImplementedException();
}
2.接下來實現這個GetCustomers() 方法,它調用DbContext.Database的SqlQuery方法DbContext.Database
如Listing 10-5所示.
Listing 10-5. DbContext Subclass with GetCustomers() Implementation
public class EF6RecipesContext : DbContext
{
public DbSet<Customer> Customers { get; set; }
public EF6RecipesContext() : base("name=EF6CodeFirstRecipesContext")
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Types<Customer>()
.Configure(c =>
{
c.HasKey(cust => cust.CustomerId);
c.Property(cust => cust.CustomerId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
c.Property(cust => cust.Name)
.HasMaxLength(50);
c.Property(cust => cust.Company)
.HasMaxLength(50);
c.Property(cust => cust.ContactTitle)
.HasMaxLength(50);
c.ToTable("Customer", "Chapter10");
});
}
public ICollection<Customer> GetCustomers(string company, string contactTitle)
{
return Database.SqlQuery<Customer>( "EXEC Chapter10.GetCustomers @Company,
@ContactTitle"
, new SqlParameter("Company", company)
, new SqlParameter("ContactTitle", contactTitle))
.ToList();
}
}
3.接下來的這個代碼段Listing 10-6 就是調用GetCustomers存儲過程.
Listing 10-6. Querying the Model with the GetCustomers Stored Procedure via the GetCustomers()
Method
//插入一些Customer,讓存儲過程查詢.
using (var context = new EF6RecipesContext())
{
var c1 = new Customer {Name = "Robin Steele", Company = "GoShopNow.com",
ContactTitle="CEO"};
var c2 = new Customer {Name = "Orin Torrey", Company = "GoShopNow.com",
ContactTitle="Sales Manager"};
var c3 = new Customer {Name = "Robert Lancaster", Company = "GoShopNow.com",
ContactTitle = "Sales Manager"};
var c4 = new Customer { Name = "Julie Stevens", Company = "GoShopNow.com",
ContactTitle = "Sales Manager" };
context.Customers.Add(c1);
context.Customers.Add(c2);
context.Customers.Add(c3);
context.Customers.Add(c4);
context.SaveChanges();
}
using (var context = new EF6RecipesContext())
{
var allCustomers = context.GetCustomers("GoShopNow.com", "Sales Manager");
Console.WriteLine("Customers that are Sales Managers at GoShopNow.com");
foreach (var c in allCustomers)
{
Console.WriteLine("Customer: {0}", c.Name);
}
}
以下Listing 10-6是控制台輸出結果:
============================================================================================
Customers that are Sales Managers at GoShopNow.com
Customer: Orin Torrey
Customer: Robert Lancaster
Customer: Julie Stevens
=============================================================
它是如何工作的?
為了能接收資料庫中的存儲過程里返回的實體集合,我們在DbContext子類中實現了 GetCustomers()方法,該方法用DbContext.Database.SqlQuery<T>() 來執行存儲過程 GetCustomers(它的定義見Listing 10-3). SqlQuery() 方法能用來執行返回一個結果集的 DML(數據操縱語言)語句. 該方法接收一個SQL語句的字元串。SqlQuery<T>() 泛型方法返回一個開發人員指定的強類型的實體集。