無論ORM有多麼強大,總會出現一些特殊的情況,它無法滿足我們的要求。在這篇文章中,我們介紹幾種執行SQL的方法。 ...
無論ORM有多麼強大,總會出現一些特殊的情況,它無法滿足我們的要求。在這篇文章中,我們介紹幾種執行SQL的方法。
表結構
在具體內容開始之前,我們先簡單說明一下要使用的表結構。
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
}
在Category
定義了兩個欄位:CategoryID
、CategoryName
。
public class SampleDbContext : DbContext
{
public virtual DbSet<Category> Categories { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var sqlConnectionStringBuilder = new SqlConnectionStringBuilder {
DataSource = "10.0.1.5",
InitialCatalog = "TestDataBase",
UserID = "sa",
Password = "******"
};
optionsBuilder.UseSqlServer(sqlConnectionStringBuilder.ConnectionString);
base.OnConfiguring(optionsBuilder);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
EntityTypeBuilder<Category> entityTypeBuilder = modelBuilder.Entity<Category>();
entityTypeBuilder.ToTable("Category");
entityTypeBuilder.HasKey(e => e.CategoryID);
entityTypeBuilder.Property(e => e.CategoryID).UseSqlServerIdentityColumn();
}
}
我們使用SampleDbContext
來訪問資料庫。
FromSql執行SQL語句
Entity Framework Core為DbSet<TEntity>
提供了一個擴展方法FromSql
,用於執行SQL語句或存儲過程,以下示例使用FromSql
載入所有的數據。
using (var dataContext = new SampleDbContext()) {
var query = dataContext.Categories.FromSql("select * from Category");
var result = query.ToList();
}
對於帶有參數的SQL語句,我們使用C# 6 語法將SQL寫成如下:
using (var dataContext = new SampleDbContext()) {
var categoryID = 1;
var query = dataContext.Categories.FromSql($"select * from Category where CategoryID={categoryID}");
var result = query.ToList();
}
註意:這裡不是直接使用拼接的方式處理SQL,而是轉化為參數化的SQL語句,這有助於防止SQL註入攻擊。我們可以使用SQL Server Profiler幫我們驗證:
exec sp_executesql N'select * from Category where CategoryID=@p0
',N'@p0 int',@p0=1
如果您不使用C# 6的語法特征,我們必須使用 @p0、@p1 ... @pn 做為SQL語句的參數:
using (var dataContext = new SampleDbContext()) {
var categoryID = 1;
var categoryName = "Product";
var query = dataContext.Categories.FromSql("select * from Category where CategoryID=@p0 and CategoryName=@p1"
categoryID, categoryName);
var result = query.ToList();
Assert.NotNull(result);
}
在上述SQL語句中中,將@p0
映射到categoryID
、@ p1
映射到categoryName
。
FromSql
擴展方法返回的是IQueryable<TEntity>
對象,要們還可以接著使用一些Linq的方法,示例如下:
using (var dataContext = new SampleDbContext()) {
var categoryID = 1;
var query = dataContext.Categories.FromSql("select * from Category")
.Where(item => item.CategoryID == categoryID)
.OrderBy(item => item.CategoryName);
var result = query.ToList();
}
不過在這裡,使用的是子查詢,使用SQL Server Profiler捕獲到的SQL語句如下:
exec sp_executesql N'SELECT [item].[CategoryID], [item].[CategoryName]
FROM (
select * from Category
) AS [item]
WHERE [item].[CategoryID] = @__categoryID_1
ORDER BY [item].[CategoryName]',N'@__categoryID_1 int',@__categoryID_1=1
提示:使用
FromSql
時,需要在執行的SQL語句中返回所有列,並且列名必須與實體屬性名相匹配,否則執行會出錯。
FromSql執行存儲過程
存儲過程與SQL語句寫法基本一致,使用存儲過程的示例如下:
using (var dataContext = new SampleDbContext()) {
var categoryID = 1;
var query = dataContext.Categories.FromSql($"GetCategoryById {categoryID}");
var result = query.ToList();
Assert.NotNull(result);
}
這些參數的順序必須與存儲過程參數的順序一致。
提示:使用
FromSql
執行存儲過程時,如果使用'Where'、'OrderBy'等Linq語法,這些操作不會生成SQL語句,而是在.Net中對存儲過程返回的集合進行過濾與排序。
ExecuteSqlCommand
在DbContext
暴露了一個Database
屬性,它包括一個ExecuteSqlCommand
方法。此方法返回一個整數,表示執行的SQL語句影響的行數。有效的操作是INSERT
、UPDATE
和DELETE
,不能用於返回實體。
using (var dataContext = new SampleDbContext())
{
var categoryID = 1;
var categoryName = "Product";
var result = dataContext.Database.ExecuteSqlCommand($"UPDATE dbo.Category SET CategoryName={categoryName} WHERE CategoryID={categoryID}");
}
總結
本節介紹了Entity Framework Core中執行SQL語句和存儲過程的幾種方法, 希望對您有幫助,謝謝!
作者:Sweet Tang
本文地址:http://www.cnblogs.com/tdfblog/p/execute-sql-stored-procedure-in-entity-framework-core.html
歡迎轉載,請在明顯位置給出出處及鏈接。