<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          推薦學(xué)習(xí):EF Core 開發(fā)實(shí)踐規(guī)范!

          共 7290字,需瀏覽 15分鐘

           ·

          2021-04-08 21:40




          嚴(yán)重問(wèn)題

          客戶端求值


          • 如where條件包含的GetValueOrDefault()不能被翻譯成sql語(yǔ)句


          • 不規(guī)范代碼段例子


          public async Task<List<Person>> GetPersonsAsync()
          {
          var results = await _context.Person
          .Where(p => p.State.GetValueOrDefault() == 1)
          .ToListAsync()
          return results;
          }


          客戶端與服務(wù)器評(píng)估


          作為一般規(guī)則,Entity Framework Core 會(huì)嘗試盡可能全面地評(píng)估服務(wù)器上的查詢。EF Core 將查詢的一部分轉(zhuǎn)換為可在客戶端評(píng)估的參數(shù)。系統(tǒng)將查詢的其余部分(及生成的參數(shù))提供給數(shù)據(jù)庫(kù)提供程序,以確定要在服務(wù)器上評(píng)估的等效數(shù)據(jù)庫(kù)查詢。EF Core 支持在頂級(jí)投影中進(jìn)行部分客戶端評(píng)估(基本上為最后一次調(diào)用 Select())。如果查詢中的頂級(jí)投影無(wú)法轉(zhuǎn)換為服務(wù)器,EF Core 將從服務(wù)器中提取任何所需的數(shù)據(jù),并在客戶端上評(píng)估查詢的其余部分。如果 EF Core 在頂級(jí)投影之外的任何位置檢測(cè)到不能轉(zhuǎn)換為服務(wù)器的表達(dá)式,則會(huì)引發(fā)運(yùn)行時(shí)異常。請(qǐng)參閱查詢工作原理,了解 EF Core 如何確定哪些表達(dá)式無(wú)法轉(zhuǎn)換為服務(wù)器。


          在 3.0 版之前,Entity Framework Core 支持在查詢中的任何位置進(jìn)行客戶端評(píng)估。


          頂級(jí)投影中的客戶端評(píng)估


          在下面的示例中,一個(gè)輔助方法用于標(biāo)準(zhǔn)化從 SQL Server 數(shù)據(jù)庫(kù)中返回的博客的 URL。由于 SQL Server 提供程序不了解此方法的實(shí)現(xiàn)方式,因此無(wú)法將其轉(zhuǎn)換為 SQL。查詢的所有其余部分是在數(shù)據(jù)庫(kù)中評(píng)估的,但通過(guò)此方法傳遞返回的 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;
          }


          不支持的客戶端評(píng)估


          盡管客戶端評(píng)估非常有用,但有時(shí)會(huì)減弱性能。請(qǐng)看以下查詢,其中的 where 篩選器現(xiàn)已使用輔助方法。由于數(shù)據(jù)庫(kù)中不能應(yīng)用篩選器,因此需要將所有數(shù)據(jù)提取到內(nèi)存中,以便在客戶端上應(yīng)用篩選器。根據(jù)服務(wù)器上的篩選器和數(shù)據(jù)量,客戶端評(píng)估可能會(huì)減弱性能。因此 Entity Framework Core 會(huì)阻止此類客戶端評(píng)估,并引發(fā)運(yùn)行時(shí)異常。


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


          顯式客戶端評(píng)估


          在某些情況下,可能需要以顯式方式強(qiáng)制進(jìn)行客戶端評(píng)估,如下所示


          由于數(shù)據(jù)量小,因此在進(jìn)行客戶端評(píng)估時(shí)才不會(huì)大幅減弱性能。


          所用的 LINQ 運(yùn)算符不會(huì)進(jìn)行任何服務(wù)器端轉(zhuǎn)換。


          在這種情況下,通過(guò)調(diào)用 AsEnumerable 或 ToList 等方法(若為異步,則調(diào)用 AsAsyncEnumerable 或 ToListAsync),以顯式方式選擇進(jìn)行客戶端評(píng)估。使用 AsEnumerable 將對(duì)結(jié)果進(jìn)行流式傳輸,但使用 ToList 將通過(guò)創(chuàng)建列表來(lái)進(jìn)行緩沖,因此也會(huì)占用額外的內(nèi)存。但如果枚舉多次,則將結(jié)果存儲(chǔ)到列表中可以帶來(lái)更大的幫助,因?yàn)橹挥幸粋€(gè)對(duì)數(shù)據(jù)庫(kù)的查詢。根據(jù)具體的使用情況,你應(yīng)該評(píng)估哪種方法更適合。


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


          客戶端評(píng)估中潛在的內(nèi)存泄漏


          由于查詢轉(zhuǎn)換和編譯的開銷高昂,因此 EF Core 會(huì)緩存已編譯的查詢計(jì)劃。緩存的委托在對(duì)頂級(jí)投影進(jìn)行客戶端評(píng)估時(shí)可能會(huì)使用客戶端代碼。


          EF Core 為樹型結(jié)構(gòu)中客戶端評(píng)估的部分生成參數(shù),并通過(guò)替換參數(shù)值重用查詢計(jì)劃。但表達(dá)式樹中的某些常數(shù)無(wú)法轉(zhuǎn)換為參數(shù)。如果緩存的委托包含此類常數(shù),則無(wú)法將這些對(duì)象垃圾回收,因?yàn)樗鼈內(nèi)员灰谩?/span>


          如果此類對(duì)象包含 DbContext 或其中的其他服務(wù),則會(huì)導(dǎo)致應(yīng)用的內(nèi)存使用量逐漸增多。此行為通常是內(nèi)存泄漏的標(biāo)志。只要遇到的常數(shù)為不能使用當(dāng)前數(shù)據(jù)庫(kù)提供程序映射的類型,EF Core 就會(huì)引發(fā)異常。常見原因及其解決方案如下所示:


          • 使用實(shí)例方法:在客戶端投影中使用實(shí)例方法時(shí),表達(dá)式樹包含實(shí)例的常數(shù)。如果你的方法不使用該實(shí)例中的任何數(shù)據(jù),請(qǐng)考慮將該方法設(shè)為靜態(tài)方法。如果需要方法主體中的實(shí)例數(shù)據(jù),則將特定數(shù)據(jù)作為實(shí)參傳遞給方法。


          • 將常數(shù)實(shí)參傳遞給方法:這種情況通常是由于在客戶端方法的實(shí)參中使用 this 引起的。請(qǐng)考慮將實(shí)參拆分為多個(gè)標(biāo)量實(shí)參,可由數(shù)據(jù)庫(kù)提供程序進(jìn)行映射。


          • 其他常數(shù):如果在任何其他情況下都出現(xiàn)常數(shù),則可以評(píng)估在處理過(guò)程中是否需要該常數(shù)。如果必須具有常數(shù),或者如果無(wú)法使用上述情況中的解決方案,則創(chuàng)建本地變量來(lái)存儲(chǔ)值,并在查詢中使用局部變量。EF Core 會(huì)將局部變量轉(zhuǎn)換為形參。


          建議解決


          無(wú)用追蹤


          • 無(wú)須追蹤的數(shù)據(jù)沒有加AsNoTracking


          跟蹤與非跟蹤查詢


          跟蹤行為決定了 Entity Framework Core 是否將有關(guān)實(shí)體實(shí)例的信息保留在其更改跟蹤器中。如果已跟蹤某個(gè)實(shí)體,則該實(shí)體中檢測(cè)到的任何更改都會(huì)在 SaveChanges() 期間永久保存到數(shù)據(jù)庫(kù)。EF Core 還將修復(fù)跟蹤查詢結(jié)果中的實(shí)體與更改跟蹤器中的實(shí)體之間的導(dǎo)航屬性。


          從不跟蹤無(wú)鍵實(shí)體類型。無(wú)論在何處提到實(shí)體類型,它都是指定義了鍵的實(shí)體類型。


          跟蹤查詢


          返回實(shí)體類型的查詢是默認(rèn)會(huì)被跟蹤的。這表示可以更改這些實(shí)體實(shí)例,然后通過(guò) SaveChanges() 持久化這些更改。在以下示例中,將檢測(cè)到對(duì)博客評(píng)分所做的更改,并在 SaveChanges() 期間將這些更改持久化到數(shù)據(jù)庫(kù)中。


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


          非跟蹤查詢


          在只讀方案中使用結(jié)果時(shí),非跟蹤查詢十分有用。可以更快速地執(zhí)行非跟蹤查詢,因?yàn)闊o(wú)需設(shè)置更改跟蹤信息。如果不需要更新從數(shù)據(jù)庫(kù)中檢索到的實(shí)體,則應(yīng)使用非跟蹤查詢。可以將單個(gè)查詢替換為非跟蹤查詢。


          var blogs = context.Blogs
          .AsNoTracking()
          .ToList();


          還可以在上下文實(shí)例級(jí)別更改默認(rèn)跟蹤行為:


          context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;
          var blogs = context.Blogs.ToList();


          標(biāo)識(shí)解析


          由于跟蹤查詢使用更改跟蹤器,因此 EF Core 將在跟蹤查詢中執(zhí)行標(biāo)識(shí)解析。當(dāng)具體化實(shí)體時(shí),如果 EF Core 已被跟蹤,則會(huì)從更改跟蹤器返回相同的實(shí)體實(shí)例。如果結(jié)果中多次包含相同的實(shí)體,則每次會(huì)返回相同的實(shí)例。


          非跟蹤查詢不會(huì)使用更改跟蹤器,也不會(huì)執(zhí)行標(biāo)識(shí)解析。因此會(huì)返回實(shí)體的新實(shí)例,即使結(jié)果中多次包含相同的實(shí)體也是如此。此行為與 EF Core 3.0 之前的版本中的行為有所不同,請(qǐng)參閱早期版本。


          跟蹤和自定義投影


          即使查詢的結(jié)果類型不是實(shí)體類型,默認(rèn)情況下 EF Core 也會(huì)跟蹤結(jié)果中包含的實(shí)體類型。在以下返回匿名類型的查詢中,結(jié)果集中的 Blog 實(shí)例會(huì)被跟蹤。


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


          如果結(jié)果集包含來(lái)自 LINQ 組合的實(shí)體類型,EF Core 將跟蹤它們。


          var blog = context.Blogs
          .Select(b =>
          new
          {
          Blog = b,
          Post = b.Posts.OrderBy(p => p.Rating).LastOrDefault()
          });


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


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


          EF Core 支持執(zhí)行頂級(jí)投影中的客戶端評(píng)估。如果 EF Core 具體化實(shí)體實(shí)例以進(jìn)行客戶端評(píng)估,則會(huì)跟蹤該實(shí)體實(shí)例。


          此處,由于我們要將 blog 實(shí)體傳遞到客戶端方法 StandardizeURL,因此 EF Core 也會(huì)跟蹤博客實(shí)例。


          var blogs = context.Blogs
          .OrderByDescending(blog => blog.Rating)
          .Select(blog => new
          {
          Id = blog.BlogId,
          Url = StandardizeUrl(blog)
          })
          .ToList();
          public static string StandardizeUrl(Blog blog)
          {
          var url = blog.Url.ToLower();
          if (!url.StartsWith("http://"))
          {
          url = string.Concat("http://", url);
          }
          return url;
          }


          EF Core 不會(huì)跟蹤結(jié)果中包含的無(wú)鍵實(shí)體實(shí)例。但 EF Core 會(huì)根據(jù)上述規(guī)則跟蹤帶有鍵的實(shí)體類型的所有其他實(shí)例。


          在 EF Core 3.0 之前,某些上述規(guī)則的工作方式有所不同。有關(guān)詳細(xì)信息,請(qǐng)參閱早期版本。


          沒有使用異步方法


          • 沒有優(yōu)先使用異步方法


          • 不規(guī)范代碼段例子


          public async Task<int> AddPersons(IEnumerable<Person> persons)
          {
          this._context.Person.AddRange(persons);
          return await this._context.SaveChangesAsync();
          }


          異步查詢


          當(dāng)在數(shù)據(jù)庫(kù)中執(zhí)行查詢時(shí),異步查詢可避免阻止線程。異步查詢對(duì)于在胖客戶端應(yīng)用程序中保持響應(yīng)式 UI 非常重要。異步查詢還可以增加 Web 應(yīng)用程序中的吞吐量,即通過(guò)釋放線程,以處理 Web 應(yīng)用程序中的其他請(qǐng)求。有關(guān)詳細(xì)信息,請(qǐng)參閱使用 C# 異步編程。


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


          Entity Framework Core 提供一組類似于 LINQ 方法的異步擴(kuò)展方法,用于執(zhí)行查詢并返回結(jié)果。示例包括 ToListAsync()、ToArrayAsync()、SingleAsync()。某些 LINQ 運(yùn)算符(如 Where(...) 或 OrderBy(...))沒有對(duì)應(yīng)的異步版本,因?yàn)檫@些方法僅用于構(gòu)建 LINQ 表達(dá)式樹,而不會(huì)導(dǎo)致在數(shù)據(jù)庫(kù)中執(zhí)行查詢。


          EF Core 異步擴(kuò)展方法在 Microsoft.EntityFrameworkCore 命名空間中定義 。必須導(dǎo)入此命名空間才能使這些方法可用。


          public async Task<List<Blog>> GetBlogsAsync()
          {
          using (var context = new BloggingContext())
          {
          return await context.Blogs.ToListAsync();
          }
          }


          事務(wù)濫用


          • 沒必要使用事務(wù)的場(chǎng)景使用事務(wù)


          • 不規(guī)范代碼段例子


          public async Task<bool> UpdatePersonInfo(List<Person> persons, List<Address> addresses)
          {
          using (var transaction = _dbContext.Database.BeginTransaction(IsolationLevel.ReadCommitted))
          {
          try
          {
          _dbContext.Person.UpdateRange(persons);
          await _dbContext.SaveChangesAsync();
          _dbContext.Address.UpdateRange(addresses);
          await _dbContext.SaveChangesAsync();
          transaction.Commit();
          return true;
          }
          catch (Exception ex)
          {
          transaction.Rollback();
          throw new InternalServerErrorException($"更新失敗,ErrorMessage:{ex.Message}
          InnerException:{ex.InnerException}"
          , ex);
          }
          }
          }


          使用事務(wù)


          事務(wù)允許以原子方式處理多個(gè)數(shù)據(jù)庫(kù)操作。如果已提交事務(wù),則所有操作都會(huì)成功應(yīng)用到數(shù)據(jù)庫(kù)。如果已回滾事務(wù),則所有操作都不會(huì)應(yīng)用到數(shù)據(jù)庫(kù)。


          默認(rèn)事務(wù)行為


          默認(rèn)情況下,如果數(shù)據(jù)庫(kù)提供程序支持事務(wù),則會(huì)在單次調(diào)用 SaveChanges() 時(shí)將所有更改都將應(yīng)用到事務(wù)中。如果其中有任何更改失敗,則會(huì)回滾事務(wù)且所有更改都不會(huì)應(yīng)用到數(shù)據(jù)庫(kù)。這意味著,SaveChanges() 可保證要么完全成功,要么在出現(xiàn)錯(cuò)誤時(shí)不修改數(shù)據(jù)庫(kù)。


          對(duì)于大多數(shù)應(yīng)用程序,此默認(rèn)行為已足夠。除非應(yīng)用程序確有需求,否則不應(yīng)手動(dòng)控制事務(wù)。


          控制事務(wù)


          可以使用 DbContext.Database API 開始、提交和回滾事務(wù)。以下示例顯示了在單個(gè)事務(wù)中執(zhí)行的兩個(gè) SaveChanges() 操作以及 一個(gè)LINQ 查詢。


          并非所有數(shù)據(jù)庫(kù)提供程序都支持事務(wù)。調(diào)用事務(wù) API 時(shí),某些提供程序可能會(huì)引發(fā)異常或不執(zhí)行任何操作。


          規(guī)范參考


          • 數(shù)據(jù)追蹤參考規(guī)范

            https://docs.microsoft.com/zh-cn/ef/core/querying/tracking


          • 客戶端求值參考規(guī)范

            https://docs.microsoft.com/zh-cn/ef/core/querying/client-eval


          • 異步查詢參考規(guī)范

            https://docs.microsoft.com/zh-cn/ef/core/querying/async


          • 加載相關(guān)數(shù)據(jù)參考規(guī)范

            https://docs.microsoft.com/zh-cn/ef/core/querying/related-data


          • 事務(wù)使用參考規(guī)范

            https://docs.microsoft.com/zh-cn/ef/core/saving/transactions


          github:https://github.com/cailin0630


          回復(fù) 【關(guān)閉】學(xué)關(guān)
          回復(fù) 【實(shí)戰(zhàn)】獲取20套實(shí)戰(zhàn)源碼
          回復(fù) 【福利】獲取最新微信支付有獎(jiǎng)勵(lì)
          回復(fù) 【被刪】學(xué)個(gè)
          回復(fù) 【訪客】學(xué)
          回復(fù) 【卡通】學(xué)制作微信卡通頭像
          回復(fù) 【python】學(xué)微獲取全套0基礎(chǔ)Python知識(shí)手冊(cè)
          回復(fù) 【2019】獲取2019 .NET 開發(fā)者峰會(huì)資料PPT

          臥槽:微信又能免費(fèi)提現(xiàn)了!


          副業(yè)剛需,公眾號(hào)1萬(wàn)粉絲流量主能賺多少錢?



          瀏覽 36
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲国产精品久久久 | 国产最新av | a√在线免费 | 俺也色色 | 撸撸撸在线观看 |