久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Entity Framework

 ThinkTank_引擎 2014-02-26

Entity Framework

Entity Framework 6:專家版本

Julie Lerman

隨著 Entity Framework 最新主版本 EF6 的推出,,Microsoft 對象關(guān)系映射 (ORM) 工具達(dá)到了新的專業(yè)高度,與久負(fù)盛名的 .NET ORM 工具相比已不再是門外漢,。 EF 已經(jīng)完全成熟,,正在超越以前廣泛使用的工具。

Entity Framework 已經(jīng)度過了青澀期,,它最初只是供數(shù)據(jù)庫開發(fā)者使用的工具,,后來在 .NET 社區(qū)的敏捷開發(fā)者中間引起轟動(dòng)。 它學(xué)會了如何擺脫應(yīng)用程序開發(fā)模式,,轉(zhuǎn)向了普通舊 CLR 對象 (POCO) 模型,,支持以測試和域?yàn)橹行牡能浖_發(fā),同時(shí)沒有剝奪以數(shù)據(jù)為中心的開發(fā)者的使用權(quán)利,。 一路走來,,它解決了生成代碼的性能問題和無數(shù)與質(zhì)量有關(guān)的問題,并贏得了眾多數(shù)據(jù)庫管理員 (DBA) 的青睞,。

從 EF 4.1 開始,,Microsoft 認(rèn)識到了 EF 所需的復(fù)雜性,通過推出 DbContext API 簡化了對其功能的訪問,。 同時(shí),,由于不是所有人都想使用設(shè)計(jì)器或生成代碼,它可以讓您利用自己的代碼生成模型,。 在此期間,,發(fā)生了另一項(xiàng)重大變化,,但不是功能、語法,、代碼或性能的變化,。 EF 團(tuán)隊(duì)變得更加透明,與用戶社區(qū)的互動(dòng)更加頻繁,,它開始更加流暢地提供功能發(fā)布,,而不是將它們與 Microsoft .NET Framework 捆綁在一起。 自 2012 年 EF5 發(fā)布后,,這種做法帶來了兩個(gè)方面的進(jìn)步,。 首先,從 .NET Framework 中提取所有的 Entity Framework API,,并與團(tuán)隊(duì)同時(shí)正在開發(fā)的非常規(guī)功能 API 組合在一起,。 其次,整個(gè)開發(fā)工作改用了開源模型,。 EF6 在以下網(wǎng)站中公開開發(fā):entityframework.,。 您不僅能通過會議記錄、簽入和可下載夜間生成了解團(tuán)隊(duì)所做的工作,,還可以向 EF6 提供源代碼(但是要在 EF 團(tuán)隊(duì)的完全監(jiān)督之下),。

請記住 EF6 是演變而不是革命。 幾乎您原先掌握的所有 EF 技能都沒有變化,,例如如何生成 Entity Framework 模型以及如何在您的應(yīng)用程序中使用 EF,。 盡管 EF6 是在 ORM 基礎(chǔ)上發(fā)展而來的,但是并沒有改變它根本的工作方式,。 如果您已經(jīng)投入時(shí)間學(xué)習(xí) EF,,那么這種投入將不會白費(fèi)。 EF6 在某些方面變化還是比較大的,,但是這些變化僅限于部分命名空間的變化,,如果您有準(zhǔn)備的話會很容易處理。 我會在本文最后告訴您一些有幫助的資源,。

我認(rèn)為 EF6 的功能分為以下幾類:

  1. 免費(fèi)提供的功能:這些功能屬于核心功能的一部分,。 您甚至無需知道它們有什么作用,更不必說需要知道有什么新的代碼了,。 該組包括的功能有通過重寫視圖生成引擎和查詢編譯修改來提高性能,,由于 DbContext 能使用打開的連接而獲得的穩(wěn)定性,,以及 Entity Framework 創(chuàng)建的 SQL Server 數(shù)據(jù)庫的更改設(shè)置,。
  2. 級別設(shè)置功能:改進(jìn)較大之處是 Code First 現(xiàn)在支持映射存儲過程,而在設(shè)計(jì)器中創(chuàng)建的模型已支持此功能,。 第 9 頻道視頻對此功能已進(jìn)行了頗多介紹(例如位于以下網(wǎng)址的視頻:/16wL8fz),,而且 CodePlex 網(wǎng)站提供了詳細(xì)的規(guī)范介紹,,所以我在本文中不再重復(fù)介紹這方面的信息。
  3. 另外一處更改更為有趣,。 正如我剛才提到的,,EF6 的 EF API 是從 .NET Framework 中提取的;它們現(xiàn)已完全封裝在 NuGet 程序包中,。 這意味著 EF5 采用的部分功能(例如枚舉,、空間數(shù)據(jù)支持和性能改進(jìn))不再依賴于 .NET 4.5。 所以,,如果您的 EF6 使用的是 .NET 4,,那么這些功能最終會給您帶來幫助。
  4. 我也將 EF 設(shè)計(jì)器歸入了這一類,。 從 2013 版開始,,Visual Studio 已取消此功能,但是作為 Visual Studio 的擴(kuò)展功能提供,。 對于 EF6 而言,,將設(shè)計(jì)器作為擴(kuò)展功能具有相當(dāng)大的好處。 以后團(tuán)隊(duì)將能夠直接向設(shè)計(jì)器添加功能,,包括 Entity Framework Power Tools 中當(dāng)前提供的功能,。 通過使設(shè)計(jì)器與 Visual Studio 分離,可以使 Microsoft 為 Visual Studio 2012 和 Visual Studio 2013 提供 EF6 工具,。
  5. 專家功能:這些功能是基本 EF 應(yīng)用程序示例所不具有的,、您渴望擁有的功能。 EF6 中有許多這樣的功能:支持異步查詢和保存,、返回自定義 Code First 約定,、利用新的 DbConfiguration 類型提高可擴(kuò)展性(依賴于較低級別的 EF6 IDbDependency 解析程序)、支持單元測試模擬,、可配置不穩(wěn)定連接的重試次數(shù)等,。 您無需成為認(rèn)證專家就能使用這些功能,但您在使用時(shí)肯定會感覺像專家,。

我還想重點(diǎn)介紹一個(gè)特殊類別:由社區(qū)成員貢獻(xiàn)的 EF6 代碼,。 Unai Zorrilla 添加了 DbSet.Add-Range 和 RemoveRange,利用它們可以自定義復(fù)數(shù)化和方便的 DbChangeTracker.HasChanges 方法,。 他還在開發(fā)供 EF 將來迭代使用的其他很酷的功能,。 Erik Jensen 是一位 SQL Server Compact (SQLCE) MVP,他貢獻(xiàn)的 SQLCeFunctions 與 LINQ to Entities 查詢使用的 SQL Server 函數(shù) SqlFunctions 非常相似,。 EF 視圖生成速度的大幅提高(對于大型復(fù)雜模型最為顯著)要?dú)w功于 Alireza Haghshenas 和一位名為 VSavenkov 的 CodePlex 成員,。 在 I?aki Elcoro(即 CodePlex 上的 iceclow)的幫助下,現(xiàn)在還可以定義自定義遷移操作,。 (EF 團(tuán)隊(duì)的 Rowan Miller 撰寫了一些關(guān)于此功能的博客文章,;第一篇位于以下網(wǎng)址:/ZBU0w1,。)全部參與者的名單可以在團(tuán)隊(duì)博客文章《可用的 EF6 RTM》中找到,網(wǎng)址是:/1gmDE6D,。

我將在本文中深入探討部分公開度不高的主題,,并告訴您詳細(xì)介紹其他主題的現(xiàn)有資源。

MSDN 數(shù)據(jù)開發(fā)者中心的版本歷史記錄頁面 (/1gCT0nz) 列出了所有功能,,每項(xiàng)功能提供一兩句詳細(xì)信息,,部分提供指向更多信息的鏈接。

一切迎刃而解:性能改進(jìn)與穩(wěn)定性

性能是許多軟件項(xiàng)目的軟肋,,Entity Framework 從一開始就受到了許多性能方面的批評,。 但是,EF 的每一次迭代都給這個(gè)方面帶來了巨大的改進(jìn),。

對性能影響最大的因素之一是首次使用應(yīng)用程序進(jìn)程中上下文時(shí)的啟動(dòng)時(shí)間,。 但是,我們可以通過多種方法改善啟動(dòng)時(shí)間,。 希望您已經(jīng)從我的文章或其他資源中了解這些方法,,例如以下網(wǎng)址提供的關(guān)于性能問題的 MSDN 文章:/3D6AiC

通常影響性能的啟動(dòng)步驟是映射視圖的生成,,EF 會利用此過程創(chuàng)建相關(guān)的 SQL,,用來查詢模型中的每個(gè)實(shí)體集。 當(dāng)應(yīng)用程序運(yùn)行時(shí),,會利用這些視圖,,因此對于部分查詢而言,EF 不必動(dòng)態(tài)創(chuàng)建 SQL,。 無論使用 EF 設(shè)計(jì)器還是使用 Code First 創(chuàng)建模型,,都會進(jìn)行視圖生成。 為了節(jié)省時(shí)間,,可以預(yù)先生成這些視圖,,再將其編譯到應(yīng)用程序中。

對于大型復(fù)雜的模型而言,,視圖生成尤其耗時(shí),。 EF6 對此過程進(jìn)行了改進(jìn),使得無論預(yù)先生成視圖還是在運(yùn)行時(shí)生成視圖,,都能顯著提高速度,。 請注意,EF 6.0.0 版本的一項(xiàng)缺陷妨礙了此功能,,但是該缺陷在 EF 6.0.1(于同一天發(fā)布)中得到了糾正,,(在編寫時(shí))采用通過 NuGet 獲得的默認(rèn)程序包。 此外,由于對運(yùn)行時(shí) EF 使用這些生成視圖的方式進(jìn)行了改進(jìn),,因而改善了查詢執(zhí)行時(shí)間,。 小模型或簡易模型的視圖生成過去從來不是問題,。 但是,,許多企業(yè)的模型都有數(shù)百個(gè)實(shí)體,同樣包括繼承,、關(guān)系和其他復(fù)雜問題,。 此更改將使這些企業(yè)大為受益。

關(guān)于如何使用 Entity Framework 程序集中的 Ngen,,請參閱 EF6 發(fā)布的公告博客文章中的另一篇性能筆記,,網(wǎng)址是:/1gmDE6D

LINQ Contains 的編譯速度更快 EF 團(tuán)隊(duì)不斷地調(diào)整查詢創(chuàng)建方式,,該團(tuán)隊(duì)重點(diǎn)進(jìn)行的一項(xiàng)更改是如何對使用 LINQ Contains 的查詢進(jìn)行編輯,。 說得更清楚些,就是提高了編譯進(jìn)程的性能,。 由于生成的 SQL 沒有變化,,因此數(shù)據(jù)庫的查詢執(zhí)行不受影響。

SQL Server 數(shù)據(jù)庫創(chuàng)建 EF6 其中一項(xiàng)穩(wěn)定性的改進(jìn)與數(shù)據(jù)庫創(chuàng)建有關(guān),。 Model First 和 Code First 工作流都能為您創(chuàng)建數(shù)據(jù)庫,。 如果該數(shù)據(jù)庫采用 SQL Server,EF 現(xiàn)在針對 SQL Server 數(shù)據(jù)庫采用了一項(xiàng)“最佳實(shí)踐”,,即將數(shù)據(jù)庫的 READ_COMMITTED_SNAPSHOT 設(shè)置配置為 ON,。 這意味著在默認(rèn)情況下,數(shù)據(jù)庫會在每次更改時(shí)都為自己創(chuàng)建一個(gè)快照,。 在實(shí)際數(shù)據(jù)庫中執(zhí)行更新時(shí),,會對該快照執(zhí)行查詢。 我在最近一篇博客文章“What’s that Read_Committed_Snapshot Transaction Support for EF6 About Anyway?”(Read_Committed_Snapshot 事務(wù)究竟支持 EF6 的哪一點(diǎn),?)中對此功能進(jìn)行了介紹,,網(wǎng)址是:/14FDpZI

重用打開連接 最后,,消除了一項(xiàng)令人心煩的限制:EF6 可讓您對打開的 DbConnection 執(zhí)行上下文調(diào)用,。 在過去,如果您顯式打開一個(gè)連接后執(zhí)行使用該連接的 EF 命令,,或者,,如果您試圖重用已被另一個(gè)上下文調(diào)用打開的連接,將會引發(fā)異常并顯示如下消息,,“實(shí)體連接只能用關(guān)閉的 DbConnection 構(gòu)造,。”現(xiàn)在,,EF6 會非常樂意讓您重用已經(jīng)打開的連接,。

專家增強(qiáng)功能

異步支持 在我 2013 年 3 月的數(shù)據(jù)點(diǎn)專欄文章“Playing with the EF6 Alpha”(小試 EF6 Alpha)中,,我對幾項(xiàng)功能進(jìn)行了探討(異步查詢、SaveChanges 和自定義約定)(msdn.microsoft.com/magazine/jj991973),。

異步支持將 .NET 4.5 Await 和 Async 模式引入了 EF 的 LINQ 查詢執(zhí)行方法,,增加了 FirstAsync、 FirstOrDefaultAsync,、SingleAsync,、SingleOrDefaultAsync、ToListAsync,、ForEachAsync 等,。 如需查看完整列表,請打開 System.Data.Entity.QueryableExtensions,。 DbSet 獲得了 FindAsync,,而 DbContext 獲得了 SaveChangesAsync。 自從該文章發(fā)表后,,沒有發(fā)生太多變化,,您不妨看一下該文章了解詳細(xì)情況。 此外,,Microsoft 還創(chuàng)建了部分演練和有趣的詳細(xì)規(guī)范,,您可以從我之前提到的版本歷史頁面獲取這些信息。

自定義代碼約定 在該文章中,,我還介紹了自定義 Code First 約定,,當(dāng)然也是另一項(xiàng)專家功能。 在 Code First 最初版本中 EF 團(tuán)隊(duì)對此進(jìn)行了開發(fā),,但是由于發(fā)布受阻,,該團(tuán)隊(duì)被迫對其進(jìn)行擱置,使得許多開發(fā)者非常失望,。

假定您要將一個(gè)公共映射作為一般規(guī)則映射到您的實(shí)體或?qū)傩浴? 現(xiàn)在,,您可以將其定義為一個(gè)約定,無需單獨(dú)為模型每個(gè)實(shí)體或?qū)傩灾付ㄓ成?,而且它會被全面?yīng)用到所有實(shí)體上,。 例如,如果您要用 50 個(gè)字符表示數(shù)據(jù)庫中的每個(gè)字符串屬性,,無論您的數(shù)據(jù)庫提供程序使用何種默認(rèn)值,,您都可以將此規(guī)則指定為約定。 由于約定采用 Code First Fluent API,,因此如果您這樣配置映射的話,,生成約定應(yīng)該會感覺非常熟悉。

  1.  
  2.           modelBuilder.Properties<String>().Configure(p => p.HasMaxLength(50))
  3.         

現(xiàn)在,此模型的每一個(gè)字符串將映射到一個(gè) 50 字符的數(shù)據(jù)庫列,。 與 Fluent 或注釋配置一樣,,您可以指定屬性或?qū)嶓w的約定,并控制繼承映射,。 通過約定來影響關(guān)系是基于模型的約定要處理的一個(gè)不太常見且更為復(fù)雜的任務(wù),。 有關(guān)詳細(xì)信息,請?jiān)L問 /1gAqcMq,。 您還可使用約定作為數(shù)據(jù)注釋,。 當(dāng) Code First 生成模型時(shí)可以使用一個(gè)用來執(zhí)行約定的層次結(jié)構(gòu),。 默認(rèn)情況下,,內(nèi)置約定先運(yùn)行,自定義約定后運(yùn)行,。 但是,,您可以強(qiáng)制使自定義約定在內(nèi)置約定前執(zhí)行。 有關(guān)示例請參閱“Custom Code First Conventions”(自定義 Code First 約定),,網(wǎng)址:/14dg0CP,。

連接復(fù)原 如果在 EF 嘗試執(zhí)行查詢或保存更改時(shí)連接斷開,您現(xiàn)在可以讓 EF 重試,。 盡管斷開連接是企業(yè) Intranet 的問題,,但是經(jīng)證明連接復(fù)原對于幫助應(yīng)用程序與云連接非常有用。 使用 IDbConnectionStrategy 可以配置重試次數(shù),。 EF 中包含的 SQL Server 提供程序用來指定 default:SqlServer-ExecutionStrategy,,它會顯示錯(cuò)誤消息告知調(diào)整瞬態(tài)連接引發(fā)異常的策略。 另外一個(gè)策略 SqlAzureExecutionStrategy 通過微調(diào)可以連接 Windows Azure SQL 數(shù)據(jù)庫,。

最簡單的策略指定方法是使用新的 DbConfiguration 類,,使用該類可以很容易配置特定數(shù)據(jù)庫提供程序的行為。 以下命令可以讓 EF 針對 SqlClient 使用 SQLAzureExecutionStrategy:

  1.  
  2.           SetExecutionStrategy (SqlProviderServices.ProviderInvariantName,
  3.   () => new SqlAzureExecutionStrategy());
  4.         

不僅連接策略可以配置,,而且您還可以自己創(chuàng)建策略并根據(jù)需要通過編程暫停使用它們,。 EF 團(tuán)隊(duì)成員 Miller 在他的博客文章里介紹了如何暫停使用,網(wǎng)址是:/14gPM1y,。

我利用另一位 EF 團(tuán)隊(duì)成員 Glenn Condron 建議的方法對 SqlAzureExecutionStrategy 進(jìn)行了測試,。 為了觸發(fā)此策略尋找的特定瞬態(tài)連接故障錯(cuò)誤代碼,我利用新的 EF6 命令攔截功能引發(fā)了一個(gè)瞬態(tài)連接錯(cuò)誤,。 然后我運(yùn)行了測試,,測試結(jié)果顯示,當(dāng)我設(shè)置執(zhí)行策略時(shí),,在初次失敗后查詢重試了五次,。 一位開發(fā)者對我在博客文章中介紹的此功能有一段非常棒的評論,他說他的公司已經(jīng)感受到了此功能帶來的好處 (/HaqMA0)。

還有一個(gè)非常有趣的算法,,可以確保不同線程的重試不會全部同時(shí)執(zhí)行,。

共享 DbTransactions 和 DbConnections 我希望到現(xiàn)在您已明白,默認(rèn)情況下 EF 始終使用 DbTransaction 對數(shù)據(jù)庫進(jìn)行調(diào)用,。 例如,,當(dāng)調(diào)用 SaveChanges 時(shí),首先創(chuàng)建一個(gè) DbTransaction,,然后再將第一個(gè)命令發(fā)送到數(shù)據(jù)庫,。 EF 隨后向數(shù)據(jù)庫發(fā)送所有必要的插入、更新和刪除命令,,并最終提交事務(wù),。 如果一個(gè)命令失敗,所有以前執(zhí)行的命令將進(jìn)行回滾,。

通過啟動(dòng) TransactionScope 來包裝 EF 調(diào)用和任何其他需要包含在相同事務(wù)中的調(diào)用(未必是有關(guān)數(shù)據(jù)庫或 EF 的調(diào)用),,您始終可以替代默認(rèn)行為。 現(xiàn)在,,通過 EF6 的附加功能,,可以讓單個(gè) DbTransaction 負(fù)責(zé)多個(gè)數(shù)據(jù)庫調(diào)用。 請注意,,如果您要在事務(wù)或分布式事務(wù)中增加非數(shù)據(jù)庫邏輯來調(diào)用不同的數(shù)據(jù)庫,,您仍然需要使用 TransactionScope。

與 EF6 共享 DbTransactions 的關(guān)鍵是利用新的 BeginTransaction 方法返回對當(dāng)前 DbTransaction 的引用或利用 UseTransaction 方法,。

以下代碼所展示的是默認(rèn)行為:

  1.  
  2.           //code to create two new casinos, "casino1" & "casino2"
  3. var context = new CasinoSlotsModel();
  4. context.Casinos.AddRange(new[] { casino1, casino2 });
  5. context.SaveChanges();
  6. context.Database.ExecuteSqlCommand
  7.   ("Update Casino.Casinos set rating= " +
  8.  (int) casino.Rating)
  9.         

我的探查器顯示了每個(gè)上下文調(diào)用所使用的事務(wù),,其中一個(gè)調(diào)用 SaveChanges,用來觸發(fā)兩個(gè)插入,,一個(gè)調(diào)用 ExecuteSqlCommand,,用來觸發(fā)更新,如圖 1 所示,。


圖 1 包裝于自身事務(wù)中的獨(dú)立上下文調(diào)用命令

現(xiàn)在我要修改共享事務(wù)的代碼,,以此包裝 SaveChanges 和 ExecuteSqlCommand 調(diào)用。 我要使用新增的 DbContext.Database.BeginTransaction 對 System.Data.Entity.DbContextTransaction 進(jìn)行顯式實(shí)例化處理,,需要的話還會打開一個(gè)連接(請記住,,盡管 DbContext.Database.Connection 的命令相似,但卻返回 System.Data.Common.DbTransaction,,該事務(wù)無法被 EF 命令共享):

  1.  
  2.           using (var tx = context.Database.BeginTransaction()) {
  3.   try  {
  4.     context.SaveChanges();
  5.     context.Database.ExecuteSqlCommand
  6.       ("Update Casino.Casinos set rating= " +
  7.       (int) casino.Rating);
  8.     tx.Commit();
  9.   }
  10.   catch (Exception)  {
  11.     tx.Rollback();
  12.   }
  13. }
  14.         

圖 2 中可以看到同一事務(wù)中包裝的所有命令,。


圖 2 單個(gè)事務(wù)中所有上下文調(diào)用的命令

還有一項(xiàng)名為 UseTransaction 的新功能。 您可以啟動(dòng) DbTransaction,,然后用它來執(zhí)行 ADO.NET 調(diào)用,,然后利用 DbContext.Database.UseTransaction 甚至可以從同一事務(wù)中的單獨(dú)上下文實(shí)例來執(zhí)行 EF 調(diào)用,。 此示例位于以下網(wǎng)址:/1aEMIuX

由于 EF 現(xiàn)在可以利用已打開的連接創(chuàng)建 EntityConnection(由 ObjectContext 在后臺執(zhí)行),,還可以顯式重用打開的連接,。 同時(shí),上下文不會關(guān)閉不是自己打開的連接,。 我寫了一個(gè)簡單的測試程序,,通過它我在執(zhí)行上下文調(diào)用前打開了一個(gè)上下文連接。

  1.  
  2.           [TestMethod]
  3. public void ContextCanCreateEntityConnectionWithOpenConnection()
  4. {
  5.   using (var context = new CasinoSlotsModel())
  6.   {
  7.     context.Database.Connection.Open();
  8.     Assert.IsNotNull(context.Casinos.ToList());
  9.   }
  10. }
  11.         

執(zhí)行 ToList 調(diào)用時(shí),,DbContext 會創(chuàng)建一個(gè) ObjectContext 實(shí)例,,后者進(jìn)而創(chuàng)建一個(gè) EntityConnection。 然后,,它利用 EntityConnection 打開 DbConnection,,并在調(diào)用完成返回所有結(jié)果后關(guān)閉該 DbConnection。 在 EF5 中運(yùn)行此程序時(shí)會導(dǎo)致發(fā)生異常(“EntityConnection 只能使用關(guān)閉的 DbConnection 進(jìn)行構(gòu)造”),,但是由于行為發(fā)生了變化,,它在 EF6 中卻能成功運(yùn)行,。 如果您要進(jìn)一步控制連接狀態(tài),,此更改可以讓您重用連接。 規(guī)范建議在以下情況下使用,,例如“在不能保證連接的狀態(tài)時(shí),,共享組件之間的連接?!?

AddRange 和 RemoveRange 如前所述,,AddRange 和 RemoveRange 由社區(qū)成員 Zorrilla 貢獻(xiàn)。 每個(gè)方法將可枚舉的單個(gè)實(shí)體類型作為自己的參數(shù),。 在共享 DbTransactions 部分的第一個(gè)代碼示例中,,我在傳入 Casino 實(shí)例數(shù)組時(shí)使用了 AddRange。

  1.  
  2.           context.Casinos.AddRange(new[] { casino1, casino2 });
  3.         

由于默認(rèn)情況下 Entity Framework 在每個(gè)添加和刪除方法中調(diào)用 DetectChanges,,因此這些方法比一次添加或刪除單個(gè)對象時(shí)執(zhí)行速度快很多,。 如果使用 Range 方法,可以在只調(diào)用一次 DetectChanges 的同時(shí)處理多個(gè)對象,,從而顯著提高了性能,。 我用 5、50,、500,、5,000 甚至 50,000 個(gè)對象對此進(jìn)行了測試,至少在我的情形下數(shù)組大小沒有限制,,速度確實(shí)非常之快,! 請記住,,此改進(jìn)只有在使上下文作用于對象時(shí)有效,對于 SaveChanges 則無效,。 調(diào)用 SaveChanges 仍然一次只執(zhí)行一個(gè)數(shù)據(jù)庫命令,。 因此,當(dāng)您快速將 50,000 個(gè)對象添加到上下文中時(shí),,在調(diào)用 SaveChanges 時(shí)仍然要單獨(dú)執(zhí)行 50,000 個(gè)插入命令,,恐怕您在實(shí)際系統(tǒng)中是不會這樣做的。

另一個(gè)方面,,對于在不需要 EF 跟蹤對象的情況下對批量操作的實(shí)現(xiàn)支持 (/16tMHw4) 及通過一次數(shù)據(jù)庫調(diào)用同時(shí)發(fā)送多個(gè)命令的批量操作的討論由來已久 (/PegT17),。 盡管這兩種功能在初始 EF6 版本中都沒有采用,但是兩者都非常重要,,并計(jì)劃在將來版本中采用,。

與您的編碼風(fēng)格沖突較少 在 .NET 中,可以通過重寫 System.Object.Equals 方法來定義系統(tǒng)的等同性規(guī)則,。 但是,,Entity Framework 有自己確定被跟蹤實(shí)體等同性的方法,而且此方法依賴于標(biāo)識,。 如果您已經(jīng)重寫了 Equals(及 Equals 所依賴的 GetHashCode 方法),,您的 Entity Framework 更改行為跟蹤可能會出現(xiàn)問題。 Petar Paar 在他的博客文章中非常清楚地展示了此問題,,網(wǎng)址:/GJcohQ,。 為了糾正這個(gè)問題,EF6 現(xiàn)在使用自己的 Equals 和 GetHashCode 邏輯來執(zhí)行更改跟蹤任務(wù),,而忽略您可能已編寫的任何自定義 Equals 和 GetHashCode 邏輯,。 但是,您仍然可以在自己的域邏輯中顯式調(diào)用您自己的自定義方法,。 通過這種方法,,這兩種方式就能和諧共處。

如果您非常重視圖形和聚合,,可能需要在其他類型中嵌套類型,。 但是,Code First 模型生成器無法發(fā)現(xiàn)嵌套類型,,進(jìn)而無法在模型中創(chuàng)建實(shí)體或復(fù)雜類型,。 圖 3 顯示了一個(gè)嵌套類型示例:Address。 由于我只會在 Casino 類型中使用 Address,,因此我將它嵌套在了 Casino 類中,。 由于 Address 本身不需要標(biāo)識,因此我還將 Address 創(chuàng)建為域驅(qū)動(dòng)設(shè)計(jì) (DDD) 值對象,。 (請參閱我 2013 年 10 月的數(shù)據(jù)點(diǎn)專欄,,“Coding for Domain--Driven Design:Tips for Data-Focused Devs, Part 3”(域驅(qū)動(dòng)設(shè)計(jì)的編碼:以數(shù)據(jù)為中心開發(fā)的提示,,第 3 部分)詳細(xì)了解 DDD 值對象,網(wǎng)址:msdn.microsoft.com/magazine/dn451438,。

圖 3 我的含有嵌套 Address 類型的 Casino 類

  1.  
  2.           public class Casino()
  3. {
  4.   //...other Casino properties & logic
  5.   public Address PhysicalAddress { get; set; }
  6.   public Address MailingAddress { get; set; }
  7.   public class Address:ValueObject<Address>
  8.   {
  9.     protected Address(){    }
  10.     public Address(string streetOrPoBox, string city,
  11.                    string state,string postalCode)
  12.     { City = city;
  13.       State = state;
  14.       PostalCode = postalCode;
  15.       StreetOrPoBox = streetOrPoBox; }
  16.     public string StreetOrPoBox { get; private set; }
  17.     public string City { get; private set; }
  18.     public string State { get; private set; }
  19.     public string PostalCode { get; private set; }
  20.   }
  21. }
  22.         

我使用 EF Power Tools 獲得了模型的可視化表示,而且在圖 4 中我展示了使用 EF5 和 EF6 時(shí)分別得到的 Casino 實(shí)體,。 EF5 沒有識別出嵌套的類型,,并且在模型中未包含 Address 或依賴屬性(PhysicalAddress 和 MailingAddress)。 但是,,EF6 能夠檢測到嵌套的類型,,可以看出模型中表示的 Address 字段。


圖 4 與 EF5 不同,,EF6 能夠看到嵌套的 Address 類型并包含依賴屬性,。

支持嵌套類型的相同內(nèi)部更改還解決了另一個(gè)問題。 此問題因同一項(xiàng)目中不同命名空間下名稱相同的多個(gè)類型而引起,。 以前,,當(dāng) EF 從 EDMX 中讀取元數(shù)據(jù)并在程序集中尋找匹配的類型時(shí),它不會注意命名空間,。

通常,,此問題造成的后果是在與包含實(shí)體的模型相同的項(xiàng)目中包含非 EF 表示的實(shí)體。 所以我的模型中可能包含代碼生成的如下 PokerTable 類:

  1.  
  2.           namespace CasinoEntities
  3. {
  4.   public partial class PokerTable
  5.   {
  6.     public int Id { get; set; }
  7.     public string Description { get; set; }
  8.     public string SerialNo { get; set; }
  9.   }
  10. }
  11.         

還可能包含不在我的模型中但在同一項(xiàng)目中的 DTO 類:

  1.  
  2.           namespace Casino.DataTransferObjects
  3. {
  4.   public class PokerTable
  5.   {
  6.     public int Id { get; set; }
  7.     public string Description { get; set; }
  8.     public string SerialNo { get; set; }
  9.   }
  10. }
  11.         

如果項(xiàng)目以 EF5 為目標(biāo),,當(dāng)生成項(xiàng)目時(shí)會看到以下錯(cuò)誤:

CLR 類型到 EDM 類型的映射不明確,,因?yàn)槎鄠€(gè) CLR 類型與 EDM 類型“PokerTable”匹配。以前找到的是 CLR 類型“MyDtos.PokerTable”,,新找到的則是 CLR 類型“EDMXModel.DTOs.PokerTable”,。

在使用 EDMX 設(shè)計(jì)時(shí)會看到此錯(cuò)誤,。 如果使用 Code First,在遇到相同情形時(shí) — 兩個(gè)匹配的類名稱相同但命名空間不同,,并且其中一個(gè)類位于模型中 — 當(dāng)模型生成器開始解釋 Code First 模型時(shí),,您會在運(yùn)行時(shí)發(fā)現(xiàn)此問題,。

長期以來,,此問題一直令人困擾,。 我讀完該消息后問我的計(jì)算機(jī):“您看到不同的命名空間了嗎,? 在嗎,?”我還收到了很多經(jīng)歷過此問題的朋友、客戶和其他開發(fā)者發(fā)來的電子郵件,。

EF6 現(xiàn)在能夠識別命名空間并允許這種情形存在。 關(guān)于引起這兩點(diǎn)變化的內(nèi)部機(jī)制的詳細(xì)信息,,請閱讀 Arthur Vickers 發(fā)表的博客文章,,網(wǎng)址:/Wi1rZA

將上下文配置移到代碼中 在您的 app.config 或 web.config 文件中有許多設(shè)置可用來定義上下文的使用方式,。 例如,,您可以指定數(shù)據(jù)庫初始化、遷移或默認(rèn)數(shù)據(jù)庫提供程序,。 我采用的添加這些設(shè)置的方法通常是復(fù)制和粘貼,,因?yàn)檫@些設(shè)置太難記,,牽涉到許多字符串,。 現(xiàn)在有了 EF6,,您可以使用 DbConfiguration 類在代碼中聲明許多上下文配置,。 在三月的數(shù)據(jù)點(diǎn)專欄中,,我對此進(jìn)行了試用,,結(jié)果遇到了爭用條件造成的缺陷,我對此進(jìn)行了報(bào)告并進(jìn)行了修復(fù),。 現(xiàn)在我再來談一下 DbConfigurations(又稱為基于代碼的配置),。 請注意,,在談到 Code First 配置映射,、DbConfiguration 設(shè)置及用于定義更改模型時(shí)數(shù)據(jù)庫遷移方法的 DbMigrationConfigurations 時(shí),會有很多令人困惑的地方,。 DbConfiguration 以 DbContext 設(shè)置為目標(biāo),。

DbConfiguration 依靠 EF6 的另一超級專家、較低級別的功能:支持依賴關(guān)系解析,,與 ASP.NET MVC 和 Web API 中使用的 IDependencyResolver 相似,。 依賴關(guān)系解析使您可以使用代碼中的服務(wù)定位器模式與控制反轉(zhuǎn) (IoC) 模式,使 EF6 能夠從實(shí)現(xiàn)公共接口的分層可用對象中進(jìn)行選擇,。 本例中的根接口是 IDbDependencyResolver。 盡管 EF6 包含許多 DbConfigurations 可供其發(fā)現(xiàn)和在上下文設(shè)置中放置優(yōu)先順序,,但也可以利用依賴關(guān)系解析向 EF 中添加新功能。 我會繼續(xù)介紹部分配置,,我會在 /QKtvCr 上為您介紹功能規(guī)范,,使您進(jìn)一步了解 IDbDependencyResolver。

您可以使用 DbConfiguration 指定熟悉的 EF6 上下文規(guī)則及新設(shè)置,。 圖 5 所示的示例配置類包含 EF 用來取代其默認(rèn)行為的一系列不同的設(shè)置,。 可以注意到,,設(shè)置放在了類構(gòu)造函數(shù)中,。

圖 5 示例配置類

  1.  
  2.           public class CustomDbConfiguration : DbConfiguration
  3. {
  4.   public CustomDbConfiguration()
  5.   {
  6.     SetDefaultConnectionFactory(new LocalDbConnectionFactory("v11.0"));
  7.     SetDatabaseInitializer
  8.       (new MigrateDatabaseToLatestVersion<CasinoSlotsModel, Configuration>());
  9.     //SetDatabaseInitializer(new MyInitializer());
  10.     SetExecutionStrategy("System.Data.SqlClient", 
  11.       () => new SqlAzureExecutionStrategy());
  12.     AddInterceptor(new NLogEfCommandInterceptor());
  13.     SetPluralizationService(new CustomPluralizationService());
  14.   }
  15. }
  16.         

SetDefaultConnectionFactory 替換了配置文件 entityframework 部分中可能已經(jīng)使用的 DefaultConnection-Factory 標(biāo)記。 SetDatabaseInitializer 取代了在配置文件中或在應(yīng)用程序啟動(dòng)時(shí)指定初始值設(shè)定項(xiàng)或遷移配置的操作,。 我提供了兩個(gè)示例,,但其中一個(gè)已注釋掉。 一旦在 EF 查詢或其他執(zhí)行命令期間發(fā)生連接中斷,,SetExecutionStrategy 可以用來指定處理辦法,。 SetPluralizationService 公開了 EF6 另一項(xiàng)新功能:即創(chuàng)建自定義復(fù)數(shù)化的能力。 稍后我會對此進(jìn)行詳細(xì)說明,。

有許多其他方法會影響這些內(nèi)置依賴關(guān)系解析程序的上下文。 MSDN 文檔“IDbDepen-dencyResolver Services”(IDbDepen-dencyResolver 服務(wù))(/13Aojso) 列出了 DbConfiguration 提供的所有解析程序,。 當(dāng)提供程序編寫人員需要注入上下文與提供程序交互的規(guī)則和邏輯時(shí),,依賴關(guān)系解析還可用于幫助他們解決部分問題。

查詢和命令攔截 我剛才沒有提到 CustomDbConfiguration 對 AddInterceptor 的使用,。 DbConfiguration 在 IDbDependencyResolvers 中能做的不止是推送。 EF6 的另一項(xiàng)新功能是能夠攔截查詢和命令,。 在攔截查詢和命令的同時(shí),,您可以訪問即將發(fā)送至數(shù)據(jù)庫的生成 SQL 及這些命令返回的結(jié)果。 使用此信息可以記錄 SQL 命令甚至修改它們,,并告訴 EF 使用更新的命令,。 盡管我非常喜歡使用此功能,我還是想留出些空間,,建議您閱讀 Arthur Vickers 介紹此功能的三章博客系列中的第 3 章:“EF6 SQL Logging – Part 3:Interception building blocks”(EF6 SQL 日志記錄 — 第 3 章:攔截構(gòu)建基塊)(/19om5du),,其中有指向第 1 章(“Simple Logging”(簡單日志記錄))和第 2 章(“Changing the content/formatting”(更改內(nèi)容/格式))的鏈接。

自定義 EF 復(fù)數(shù)化 在討論自定義 EF 復(fù)數(shù)化的功能之前,,我要確切地知道您是否了解其默認(rèn)行為,。 EF 利用內(nèi)部復(fù)數(shù)化服務(wù)處理三項(xiàng)任務(wù):

  1. 在 Database First 中,它要確保實(shí)體采用單數(shù)名稱,。 因此,,如果數(shù)據(jù)庫表的名稱是 People,在模型中它會變成 Person,。
  2. 在 Database 或 Model First 的 EF 設(shè)計(jì)器中,,它會根據(jù)實(shí)體名稱創(chuàng)建復(fù)數(shù) EntitySet 名稱(DbSets 的基礎(chǔ))。 例如,,服務(wù)會確保 Person 實(shí)體的 EntitySet 名稱是 People,。 如果您使用 Database First 創(chuàng)建模型的話,它不會簡單地使用表名稱。
  3. 由于在 Code First 中 DbSets 采用顯式命名,,EF 會利用該服務(wù)推導(dǎo)出表名稱,。 如果開始時(shí)使用的類名稱為 Person,約定會認(rèn)為數(shù)據(jù)庫表的名稱是 People,。

該服務(wù)的作用不是作為拼寫字典(可以提供自定義拼寫的文本列表),。 它使用的是內(nèi)部規(guī)則。 除了偶爾出現(xiàn)異常外(最初我非常喜歡 Rhinoceros 這個(gè)實(shí)體名稱),,該服務(wù)最大的問題是規(guī)則采用英語,。

Zorrilla 為 EF6 創(chuàng)建了 IPluralizationService 接口以便您添加自己的邏輯。 創(chuàng)建自定義服務(wù)后,,可以按先前所示使用 DbConfiguration 將其插入,。

目前,此自定義只能使用前面列表中的第三種情形:Code First 推導(dǎo)表名稱,。 從最初的 EF6 版本開始,,該自定義不能應(yīng)用到設(shè)計(jì)器上。

有兩種使用該服務(wù)的方式,。 開始先使用基本服務(wù) — EF 中的 EnglishPluralizationService 或由其他人已經(jīng)生成的服務(wù) — 然后重寫 Singularize 或 Pluralize 方法,,添加您自己的規(guī)則。 此外,,還可以在 CustomPluralizationEntry 類中指定一對單詞,,然后將該類附加到現(xiàn)有服務(wù)。 Zorrilla 在他的博客文章中介紹了 CustomPluralizationEntry (/161JrD6),。

請留意未來的數(shù)據(jù)點(diǎn)專欄,,我會在該專欄中介紹添加復(fù)數(shù)化規(guī)則的示例(不僅是單詞對),并展示對于 Code First 數(shù)據(jù)庫映射的影響,。

Code First 的更多好處

有幾項(xiàng)針對 Code First 的新功能我還沒有介紹,,特別是 Code First 遷移。 由于空間的關(guān)系,,在此我先對它們進(jìn)行概括介紹,,再在 2014 年 1 月的數(shù)據(jù)點(diǎn)專欄中深入介紹它們:

  • 能夠創(chuàng)建遷移腳本,用來檢查哪些服務(wù)已經(jīng)運(yùn)行,,以便能夠從任何遷移點(diǎn)修復(fù)數(shù)據(jù)庫,。
  • 提高對 Migrations_History 表的控制,以適應(yīng)不同的數(shù)據(jù)庫提供程序,。
  • 能夠指定數(shù)據(jù)庫映射的默認(rèn)架構(gòu),,無需始終默認(rèn)為 dbo。
  • 能夠通過遷移處理針對同一數(shù)據(jù)庫的不同 DbContext,。
  • ModelBuilder 能夠一次性添加多個(gè) EntityTypeConfiguration,無需每個(gè)都使用一個(gè)代碼行,。

盡快使用專家,!

在我看來,,EF6 最需要銘記的一點(diǎn)是在 EF 現(xiàn)有功能的基礎(chǔ)上增加了許多很好的功能。 如果您要將項(xiàng)目從 EF5 遷移到 EF6,,需要注意部分命名空間的變化,。 關(guān)于此遷移方法,團(tuán)隊(duì)在以下網(wǎng)址提供了詳細(xì)的說明:/17eCB4U,。 除此之外,,對于使用 EF6 應(yīng)該充滿信心,它是通過 NuGet 分發(fā)的 Entity Framework 的最新穩(wěn)定版本,。 即使您不想馬上使用任何一項(xiàng)專家功能,,請記住您仍會從本文前面介紹的性能提高中獲得益處。 但我對于專家功能最感興奮,,非常感謝將這些功能也添加到 EF6 中的社區(qū)開發(fā)者,。

EF 將繼續(xù)進(jìn)行演變。 盡管 EF6 第一版的發(fā)布時(shí)間與 Visual Studio 2013 的發(fā)布時(shí)間恰好一致,,但是 EF 6.1 和更高版本已經(jīng)處于開發(fā)階段,。 您可以在 CodePlex 網(wǎng)站上關(guān)注它們的進(jìn)度。

Julie Lerman 是 Microsoft MVP,、.NET 導(dǎo)師和顧問,,住在佛蒙特州的山區(qū)。您可以在全球的用戶組和會議中看到她對數(shù)據(jù)訪問和其他 Microsoft .NET 主題的演示,。她是《Programming Entity Framework》(2010) 以及“代碼優(yōu)先”版 (2011) 和 DbContext 版 (2012)(均出自 O’Reilly Media)的作者,,博客網(wǎng)址為 /blog。通過她的 Twitter(網(wǎng)址為 twitter.com/julielerman)關(guān)注她,,并在 /PS-Videos 上觀看其 Pluralsight 課程,。

衷心感謝以下技術(shù)專家對本文的審閱:Rowan Miller (Microsoft)

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn),。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多