asp.net core系列 32 EF查詢數據 必備知識(1)

来源:https://www.cnblogs.com/MrHSR/archive/2019/02/26/10435921.html
-Advertisement-
Play Games

一.查詢的工作原理 Entity Framework Core 使用語言集成查詢 (LINQ) 來查詢資料庫中的數據。 通過 LINQ 可使用 C#(或你選擇的其他 .NET 語言)基於派生上下文和實體類編寫強類型查詢。 LINQ 查詢的表示形式會傳遞給資料庫提供程式,進而轉換為特定的資料庫查詢語言 ...


一.查詢的工作原理

  Entity Framework Core 使用語言集成查詢 (LINQ) 來查詢資料庫中的數據。 通過 LINQ 可使用 C#(或你選擇的其他 .NET 語言)基於派生上下文和實體類編寫強類型查詢。 LINQ 查詢的表示形式會傳遞給資料庫提供程式,進而轉換為特定的資料庫查詢語言(例如,適用於關係資料庫的 SQL)。

 

  1.1 查詢的生命周期, 下麵是每個查詢所經歷的過程概述:

    (1) LINQ 查詢由 E F處理,用於生成已準備好的表示形式,由資料庫提供程式處理。緩存結果,以便每次執行查詢時都不需要執行此處理。

    (2) 結果將傳遞給資料庫提供程式

      a.資料庫提供程式會識別出查詢的哪些部分可以在資料庫中求值。

      b. 查詢的這些部分會轉換為特定資料庫的查詢語言(例如,關係資料庫的 SQL)

      c. 將一個或多個查詢發送到資料庫並返回結果集(結果是來自資料庫的值,而不是實體實例)

    (3) 返回結果集處理

      a.如果這是跟蹤查詢,EF會檢查數據是否代表一個實體,已存在於上下文實例的更改跟蹤器中。

        如果是,則會返回現有實體

        如果不是,則會創建新實體、設置更改跟蹤並返回該新實體

      b.如果這是非跟蹤查詢,EF 會檢查數據是否表示此查詢結果集中的現有實體

        如果是,則會返回現有實體

        如果不是,則會創建新實體並返回該新實體

 

  1.2 執行查詢時:

    調用LINQ運算符時,只會構建查詢在記憶體中的表示形式。 只有在使用結果時,查詢才會發送到資料庫。觸發查詢發送到資料庫的最常見操作如下:

    (1) 在 for 迴圈中迴圈訪問結果

         var blogs = from b in BloggingContext.Blogs
                     select {....}

            //觸發資料庫查詢
            foreach (var item in blogs)
            {
                int maxID = item.ID;
            }

    (2) 使用 ToList、ToArray、Single、Count 等操作都會觸發資料庫查詢

        BloggingContext.Blogs.ToList();
        BloggingContext.Blogs.ToArray();
        BloggingContext.Blogs.Count();
        BloggingContext.Blogs.Single();
        BloggingContext.Blogs.First();

    (3) 將查詢結果數據綁定到 UI

 

二.LINQ 查詢

  Entity Framework Core 使用語言集成查詢 (LINQ) 來查詢資料庫中的數據。 通過 LINQ 可使用 C#(或你選擇的其他 .NET 語言)基於派生上下文和實體類編寫強類型查詢。 LINQ 查詢的表示形式會傳遞給資料庫提供程式,進而轉換為特定的資料庫查詢語言(例如,適用於關係資料庫的 SQL)。 

 

    // (1)載入所有數據
     var blogs = BloggingContext.Blogs.ToList();
    SELECT [b].[BlogId], [b].[Name], [b].[Title], [b].[Url] FROM [Blogs] AS [b]

 

    //(2)載入單個實體
     var blog = BloggingContext.Blogs.Single(b => b.BlogId == 1);
    SELECT TOP(2) [b].[BlogId], [b].[Name], [b].[Title], [b].[Url]
    FROM [Blogs] AS [b]
    WHERE [b].[BlogId] = 1

 

    //(3)篩選
    var blogs = BloggingContext.Blogs.Where(b => b.Url.Contains("dotnet")).ToList();
    SELECT [b].[BlogId], [b].[Name], [b].[Title], [b].[Url]
  FROM [Blogs] AS [b]
  WHERE CHARINDEX(N'dotnet', [b].[Url]) > 0

    

    //(4)排序
  var blogs = BloggingContext.Blogs.OrderByDescending(b => b.BlogId).Select(b=> new { b.BlogId,b.Name }).ToList();
  SELECT [b].[BlogId], [b].[Name]
  FROM [Blogs] AS [b]
  ORDER BY [b].[BlogId] DESC

 

    //(5) group  找出重覆的url,取出最大BlogId
     var blogs = from b in BloggingContext.Blogs
                        group b by new { b.Url} into gs
                        where gs.Count() >1 
                        select new
                        {
                            ID= gs.Max(b=>b.BlogId)
                        };
       //top 1
     int maxID = blogs.First().ID;
    SELECT TOP(1) MAX([b].[BlogId]) AS [ID]
    FROM [Blogs] AS [b]
    GROUP BY [b].[Url]
    HAVING COUNT(*) > 1

 

      // (6)多表join查詢
       var query = from b in context.Blogs
                        join p in context.Posts  on  b.BlogId equals p.BlogId
                        where b.BlogId == 1
                        select new { b.Name,p.Title } ;
       var bloglinq= query.ToList();
    SELECT [b].[Name], [p].[Title]
    FROM [Blogs] AS [b]
    INNER JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
    WHERE [b].[BlogId] = 1

      有關顯示 LINQ 可完成的任務的大量示例,請參閱 101 個 LINQ 示例

 

三. 客戶端求值

  EF支持部分查詢在客戶端上求值,而將其他部分推送到資料庫執行。 由資料庫提供程式確定查詢的哪些部分會在資料庫中求值。 下麵示例中 客戶端通過執行StandardizeUrl方法來返回 URL,查詢的其餘部分都是在資料庫中執行的。

    var blogs = context.Blogs
    .OrderByDescending(blog => blog.Rating)
    .Select(blog => new
    {
        Id = blog.BlogId,
        Url = StandardizeUrl(blog.Url)
    })
    .ToList();

public static string StandardizeUrl(string url) { url = url.ToLower(); if (!url.StartsWith("http://")) { url = string.Concat("http://", url); } return url; }

  

  3.1 可能的性能問題

    雖然客戶端求值非常有用,但在某些情況下可能會導致性能不佳。 請考慮以下查詢,該where中使用輔助方法。 由於無法在資料庫中執行此操作,因此blog的所有數據將被拉入記憶體中,然後會在客戶端上應用篩選器。 根據數據量以及過濾掉多少數據,可能會導致性能下降。

    var blogs = context.Blogs
    .Where(blog => StandardizeUrl(blog.Url).Contains("dotnet"))
    .ToList();

 

  3.2 為客戶端評估拋出異常

    預設情況下,當執行客戶端求值時,EF Core 將記錄警告在日誌中。可以改為引發異常或不執行任何操作。 設置如下所示

       services.AddDbContext<BloggingContext>
                (options => 
                options.UseSqlServer(connection)
                //改為引發異常
                .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning))
                );

 

四. 跟蹤與非跟蹤查詢

  跟蹤行為可控制 EF是否將有關實體實例的信息保留在其更改跟蹤器中。 如果已跟蹤某個實體,則該實體中檢測到的任何更改都會在 SaveChanges() 期間永久保存到資料庫。 EF 還會修正從跟蹤查詢中獲取的實體與先前已載入到 DbContext 實例中的實體兩者之間的導航屬性。

 

   4.1 跟蹤查詢

    預設情況下,會跟蹤返回實體類型的查詢。 這表示可以更改這些實體實例,然後通過 SaveChanges() 持久化這些更改。在以下示例中,將檢測到對Blog評分所做的更改,併在 SaveChanges() 期間將這些更改持久化到資料庫中。

        var blog = context.Blogs.SingleOrDefault(b => b.BlogId == 1);
        blog.Rating = 5;
        context.SaveChanges();

        //顯示設置與上面一樣,開啟了跟蹤查詢
        var blog = context.Blogs. AsTracking().SingleOrDefault(b => b.BlogId == 1);

    

  4.2 非跟蹤查詢

    只需要讀取數據結果方案時,非跟蹤查詢十分有用。 可以更快速地執行非跟蹤查詢,因為無需設置更改跟蹤信息。

    //設置當前查詢為非跟蹤查詢
    var blogs = context.Blogs
        .AsNoTracking()
        .ToList();
//還可以在上下文實例級別, 設置預設為非跟蹤查詢 using (var context = new BloggingContext()) { context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var blogs = context.Blogs.ToList(); }

 

   4.3跟蹤和投影

    即使查詢的結果類型不是實體類型,只要結果包含實體類型,則預設情況下也會跟蹤這些實體類型。 在以下返回匿名類型的查詢中,會跟蹤結果集中 Blog 的實例。

    var blog = context.Blogs
        .Select(b =>
            new
            {
                Blog = b,
                Posts = b.Posts.Count()
            });

    如果結果集不包含任何實體類型,則不會執行跟蹤。 在以下返回匿名類型(具有實體中的某些值,但沒有實際實體類型的實例)的查詢中,不會執行跟蹤。

      var blog = context.Blogs
        .Select(b =>
            new
            {
                Id = b.BlogId,
                Url = b.Url
            });

 

 

參考文獻

  EF查詢數據

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前文說道了Action的激活,這裡有個關鍵的操作就是Action參數的映射與模型綁定,這裡即涉及到簡單的string、int等類型,也包含Json等複雜類型,本文詳細分享一下這一過程。(ASP.NET Core 系列目錄) 一、概述 當客戶端發出一個請求的時候,參數可能存在於URL中也可能是在請求的 ...
  • 使用過代碼生成器的開發人員應該知道,通過代碼生成器生成項目的代碼,可以大大的減少重覆編碼的時間,提供項目開發的效率,將自己從繁雜重覆的代碼中解放出來。現在網路上也有很多的開源的代碼生成器或者使用比較廣泛的代碼生成器,如動軟代碼生成器相信不少開發人員使用過。有時候線上的代碼生成器生成的代碼未必百分之百 ...
  • 首先 在 EntityFrameworkCore中安裝 Microsoft.Extensions.Logging.Console 按照官方文檔 使用UseLoggerFactory 方法 (地址:https://docs.microsoft.com/zh-cn/ef/core/miscellaneo ...
  • <img src="../../img/20190224185111.png" alt="" id="zhaopian"/> //定義變數 var img = ""; //圖片點擊 $("#zhaopian").click(function () { //賦值獲取圖片路徑 img = $(this) ...
  • 一、迭代器(Iterator)通過持有迭代狀態可以獲取當前迭代元素並且識別下一個需要迭代的元素,從而可以遍歷集合中每一個元素而不用瞭解集合的具體實現方式; 實現迭代器功能的方法被稱為迭代器方法,迭代器方法的返回值類型可以是以下4種介面類型中任意一種:位於命名空間System.Collections中 ...
  • 多線程 概述 單任務處理:一個任務完成後才能進行下一個任務。 多任務處理:CPU分時操作,每個任務看似同時運行。 進程 應用程式的一個運行實例,包含程式所需資源的記憶體區域,是操作系統進行資源分配的單元,進程隔離了正在執行的不同程式。(打開某一個軟體,分配CPU,隔離其他軟體) 優點:進程間相互獨立, ...
  • Taurus.MVC是一個優秀的組件,如果要應用到已有的Asp.net MVC項目中,需要修改一下。 ...
  • 1、下載並安裝jdk. 下載地址:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 點擊Accept,根據PC配置下載32位或64位的jdk 2、配置Java環境變數 右鍵” 計算 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...