asp.net core系列 33 EF查詢數(shù)據(jù) (2)

一. 原生SQL查詢

接著上篇講。通過 Entity Framework Core 可以在使用關(guān)系數(shù)據(jù)庫時下降到原始 SQL 查詢。 在無法使用 LINQ 表達要執(zhí)行的查詢時,或因使用 LINQ 查詢而導(dǎo)致低效的 SQL 查詢時非常有用。 原始 SQL 查詢可返回實體類型,或者從 EF Core 2.1 開始,可返回模型中的查詢類型。

1.1 基本的原始SQL查詢

可以使用FromSql擴展方法,基于原始的SQL查詢,開始LINQ查詢。

var blogs = context.Blogs
            .FromSql("SELECT * FROM dbo.Blogs")
            .ToList();
   --通過sql server profiler監(jiān)聽的sql,如下所示:
        select * from dbo.blogs
1.2 原生 SQL 查詢可用于執(zhí)行存儲過程(GetMostPopularBlogs)
   var blogs = context.Blogs
        .FromSql("EXECUTE dbo.GetMostPopularBlogs")
        .ToList();
1.3 傳遞參數(shù)

在使用FromSql執(zhí)行原始sql查詢時,傳遞參數(shù)要防止SQL注入攻擊,可以在SQL查詢字符串中包含參數(shù)占位符,然后提供參數(shù)值作為附加參數(shù)。任何參數(shù)值將自動轉(zhuǎn)換為DbParameter來防止SQL注入。

   var id = 4;
       var blgos=  BloggingContext.Blogs.FromSql("select * from dbo.blogs where BlogId={0}",id).ToList();

 --通過sql server profiler監(jiān)聽的sql,如下所示:
        exec sp_executesql N'select * from dbo.blogs where BlogId=@p0',N'@p0 int',@p0=4

可以構(gòu)造 DbParameter 并將其作為參數(shù)值提供。 這樣可以在 SQL 查詢字符串中使用命名參數(shù)(與上面占位符實現(xiàn)一樣,只不過這里顯示提供了命名參數(shù)@BlogId)。

 var user = new SqlParameter("@BlogId", 4);
       var blgos=  BloggingContext.Blogs.FromSql("select * from dbo.blogs where BlogId={0}", user).ToList();
 --通過sql server profiler監(jiān)聽的sql,如下所示:
        exec sp_executesql N'select * from dbo.blogs where BlogId=@BlogId',N'@BlogId int',@BlogId=4
1.4 使用 LINQ 編寫

發(fā)送到數(shù)據(jù)庫中的 SQL 查詢可以是組合的,則可以在原始 SQL 查詢后面緊跟著使用 LINQ 運算符。 以 SELECT 關(guān)鍵字開始的 SQL 查詢一般是可組合的。以下示例使用原始SQL查詢,然后使用LINQ對其進行編寫以執(zhí)行過濾和排序。

var blgos=  BloggingContext.Blogs
                .FromSql("select  blogid,url from dbo.blogs")
                .Where(b=>b.BlogId>2)
                .OrderByDescending(b=>b.BlogId)
                 .Select(b=> new{ b.BlogId, b.Url})
                .ToList();
--通過sql server profiler監(jiān)聽的sql,原始sql成了一個子查詢,如下所示:
    SELECT [b].[BlogId], [b].[Url]
    FROM (
        select  blogid,url from dbo.blogs
    ) AS [b]
    WHERE [b].[BlogId] > 2
    ORDER BY [b].[BlogId] DESC

二. 異步查詢

當(dāng)在數(shù)據(jù)庫中執(zhí)行查詢時,異步查詢可避免阻止線程。 這有助于避免凍結(jié)富客戶端應(yīng)用程序的 UI。 異步操作還可以增加 Web 應(yīng)用程序的吞吐量,可以在等數(shù)據(jù)庫操作完成時(I/O),釋放當(dāng)前線程到線程池,該線程可去處理其他請求。

注意: EF Core 不支持在同一上下文實例上運行多個并行操作。 應(yīng)始終等待操作完成,然后再開始下一個操作。 這通常是通過在每個異步操作上使用 await 關(guān)鍵字完成的。

Entity Framework Core 提供了一組異步擴展方法,可用作執(zhí)行查詢并返回結(jié)果的 LINQ 方法的替代方法。示例包括 ToListAsync()、ToArrayAsync()、SingleAsync() 等。對于部分 LINQ 運算符(如 Where(...)、OrderBy(...) 等),沒有對應(yīng)的異步版本,因為這些方法僅用于構(gòu)建 LINQ 表達式樹,而未將查詢發(fā)送到數(shù)據(jù)庫中執(zhí)行。

下面是一個示例,注意async必須搭配await,只有await完成后才會釋放當(dāng)前EF上下文, async后面必須是Task(無返回值)或Task<T>(有返回值):

  public async Task<List<Blog>> GetBlogsAsync()
    {return await context.Blogs.ToListAsync();
    }
三. 全局查詢篩選器

全局查詢篩選器是應(yīng)用于元數(shù)據(jù)模型(通常為 OnModelCreating)中的實體類型的 LINQ 查詢謂詞(通常傳遞給 LINQ Where 查詢運算符的布爾表達式)。

下面使用 HasQueryFilter API 在 OnModelCreating 中配置查詢篩選器。

 protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //IsDeleted==1 沒有被邏輯刪除的Blog數(shù)據(jù)
            modelBuilder.Entity<Blog>().HasQueryFilter(b=>b.IsDeleted==1);
        }
var blgos=  BloggingContext.Blogs
                .FromSql("select * from dbo.blogs")
                .Where(b=>b.BlogId>2)
                .OrderByDescending(b=>b.BlogId)
                 .Select(b=> new{ b.BlogId, b.Url})
                .ToList();
--通過sql server profiler監(jiān)聽的sql,where后面加了IsDeleted==1,如下所示:
    SELECT [b].[BlogId], [b].[Url]
    FROM (
        select * from dbo.blogs
    ) AS [b]
    WHERE ([b].[IsDeleted] = 1) AND ([b].[BlogId] > 2)
    ORDER BY [b].[BlogId] DESC
 //可以在Linq查詢語句中禁用全局查詢篩選器
        BloggingContext.Blogs.IgnoreQueryFilters().ToList();

參考文獻:

原生 SQL 查詢

異步查詢

全局查詢篩選器

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容