EntityFramework Reverse POCO Code First 生成器


功能強大的(免費)實體框架工具

Julie Lerman

Julie Lerman

實體框架是開源的,因此開發社區可以在 entityframework.codeplex.com 上共享代碼。 但是不要將自己局限在那里尋找工具和擴展。 還有其他一些不錯的商業和社區驅動的工具,它們能幫助您使用實體框架取得更大成就。 在本專欄中,我想強調一些來自社區的工具和擴展。 它們是可通過 Visual Studio 庫獲得的免費 IDE 擴展,或可通過 NuGet 獲得的免費代碼庫。 甚至有一些來自特別項目和官方位外部的實體框架團隊的成員。

EntityFramework Reverse POCO Code First 生成器

仍然有很多人認為 Database First 工作流是從現有數據庫創建實體框架模型的唯一方法。 該特定工作流創建 EDMX 文件,使您在設計器中與模型進行交互。 使用設計器還意味着您依賴代碼生成器來創建實體類。 但是憑借反向工程工具,還可以使用帶有已存在數據庫的 EF Code First 來進行。 現在有三種方法可完成這項工作。 我最喜歡的是這個模板:由 Simon Hughes 開發的 EntityFramework Reverse POCO Code First 生成器 (efreversepoco.codeplex.com)。 公平地講, 另外兩個也是我廣泛使用的 Microsoft 創建的工具。 一個是 EF Power Tools Beta 的功能。關於該功能的使用,請您參閱我 2011 年 5 月的博客文章,網址為bit.ly/1ky2SAJ。 另一個是 Visual Studio EF 設計器的增強功能,包含在 Entity Framework 6.1 Tools for Visual Studio 的版本中。 現在 EF 設計器包含從現有數據庫創建 POCO 的可視化方法,並能夠通過選擇要包含在模型中的表,來解決困擾我很久的一個問題。 我在 2014 年 2 月的博客文章中演示了此功能,網址為bit.ly/1rOqUv4

Hughes 的模板於 2012 年 10 月首次發布於 CodePlex,它可以從一開始就選擇數據庫的子集。 事實上,這個工具似乎提供了我希望在 EP Power Tools 或更新的 RF6.1 設計器中添加或改進的所有功能。 不僅是我有這種感覺:在我寫這篇專欄的時候,EntityFramework Reverse POCO Code First 生成器已經有近 77,000 次下載。

您可以通過 Visual Studio 的“擴展和更新”功能安裝此模板,並支持以后項目脫機訪問該模板,您也可以在想從數據庫生成 POCO 的任何情況下,從 Web 直接使用該模板。 在添加模板之前,應將實體框架添加到項目,並在配置文件中明確指定數據庫連接字符串,因為該模板依賴於這些條件。 一旦擁有 EF 和連接字符串,您就可以通過將新項添加到 Visual Studio 中的項目來啟動模板。 如果已經安裝了此模板,您可在“已安裝”下找到它;否則,請打開“聯機”部分。 請注意,在圖 1 中,我並沒有篩選模板,但在按最熱門項目排序的列表中,EntityFramework Reverse POCO Code First 生成器排在首位。 那個位置確實給我留下了深刻的印象。

 圖 1 獲取 EntityFramework Reverse POCO Code First 生成器 
圖 1 獲取 EntityFramework Reverse POCO Code First 生成器

選擇此項會在項目中生成一個新 database.tt 模板文件。 此模板具有大量已應用默認設置的配置。 在圖 2中,您可以看到模板文件的一部分,其中顯示一些可用於影響所生成代碼的更簡單配置。 ElementsToGenerate 設置讓您能夠控制所生成類的類型(POCO、上下文、Fluent 配置、UnitOfWork)。 此配置的一個好處就是,您可以為不同的項目生成不同的項。 您可以控制命名空間及類型的命名方式。 您可以生成一些基本的 Windows Communication Foundation (WCF) 類等。 此配置還可以使您通過使用 Regex 指定表模式或視圖名稱,從而指定應包含/排除的數據庫表。 對我來說,指定對象是一個重要的功能。 但是,既然 EF6.1 設計器支持直觀地選擇數據庫對象,以便創建 Code First 模型,我發現相比之下,在 .tt 文件中指定對象名稱略顯笨拙。

A Section of the EntityFramework Reverse POCO 生成器配置文件的一部分 
圖 2 EntityFramework Reverse POCO 生成器配置文件的一部分

Reverse POCO Code First 生成器與 EF Power Tools 的反向工程功能相比的另一個顯著的優點就是性能。 但是,新 EF6.1 設計器顯著加快了代碼生成,因此對我來說,這不再是一個決定性因素。 盡管如此,Reverse POCO Code First 生成器有很多不錯的功能(例如,包括將列的默認值作為屬性的默認值)和自定義類生成方式的方法(例如,指定用於導航屬性的集合的類型),我仍然喜歡它。 我只是希望能將它與 EF 設計器合並。

此模板中的功能太多,我在這里不一一列出它的功能,而是向您展示文檔和 30 分鍾的演示視頻 (reversepoco.com),以便您能對此模板的使用有一個最佳的搶先體驗。 您還可以看到,Hughes 已經接受了在 CodePlex 上向項目發布的內容。 請記住這一重要事項:EntityFramework Reverse POCO Code First 生成器當前適用於 SQL Server 和 SQL Server CE。 EF6.1 設計器適用於這些數據庫以及任何其他更新到適於與 EF6.1 結合使用的數據庫提供程序。 我聽說 Hughes 生成器的下一代主要版本 (v3) 將可以像 EF6.1 設計器一樣,對其他數據庫(例如 Oracle、MySQL 等)進行反向工程。

實體框架實用程序

我將着重介紹的下一個庫是在 GitHub 上由 Mikael Eliasson 維護的庫 (bit.ly/UeWHGW)。 您可以在 NuGet 上搜索 EFUtilities 獲取項目中的實用程序。

這組實用程序專注於性能和添加長期被實體框架開發人員遺漏的功能:在數據庫中執行批量插入、更新和刪除操作的能力。 這些實用程序中的 EFBulkOperation 類適用於 DbContext,因此您不能將其與 ObjectContext 一起使用。 盡管很多開發人員都已攻克了這一難題,但我已經認識 Mikael 一段時間了,因此很自然就想到他的產品。 在 CodePlex 網站上還有關於實體框架在本地 API 中獲取批量操作最佳方法的討論。

該實用程序允許您在 EFBulk­Operation 類上編寫 LINQ 查詢,以執行相關操作。 作為測試,我從 AdventureWorks2012 數據庫創建了一個模型(使用我剛才討論的 EntityFramework Reverse POCO Code First 生成器工具)。 然后,我在代碼中創建了一個有 1,000 個 BusinessEntity 類型實例的列表:

 
var entityList = new List<BusinessEntity>();
for (int i = 0; i < 1000; i++)
{
  entityList.Add(new BusinessEntity{});
}

我使用標准實體框架代碼插入這些實例,然后調用 SaveChanges:

 
using (var context = new AWModel()) {
  context.BusinessEntities.AddRange(entityList);
  context.SaveChanges();
}

這引發了 1,000 條單個插入語句發送到我的 SQL Server 數據庫,整個操作通過一些重復執行,平均耗時約 6 秒。 我已經從這個計時中扣除了 EF 的預熱時間。

然后,我使用了 EFBatchOperation 類插入 1,000 個相同的 BusinessEntity 對象:

 
using (var context2 = new AWModel()) {
  EFBatchOperation.For(context2, 
    context2.BusinessEntities).InsertAll(entityList);
}

平均執行大約 12 毫秒。

請記住,在標准 EF 代碼中,我必須將所有實例添加到上下文,以便更改跟蹤器決定需要哪個 SQL 發送到服務器。 另一方面,EFBatchOperation 類不依賴於 EF 更改跟蹤器來創建 SQL。 相反,它會創建 EFUtilities 中的一個 DataReader 類,並使用早在 ADO.NET 2.0 中引進的 .NET SqlBulkCopy 類來將其傳送到數據庫。 我很高興看到這一點,因為這就是我通常所推薦的解決這個問題的路徑。 因此,這種方法不僅不強迫上下文跟蹤 1,000 個實體,它還發送單一命令到數據庫以及要插入數據的二進制流。 SQL 事件探查器不會顯示此流,因此我在 SQL 事件探查器中所看到的作為 EFBatchoperation.InsertAll 方法結果的就是這個單一命令:

 
insert bulk BusinessEntity
  ([rowguid] UniqueIdentifier,
  [ModifiedDate] DateTime)

這里有個很好的保護,如果您正在使用的數據庫提供程序沒有批量方法,實用程序將恢復到處理該請求的 EF 默認方法。 在這種情況下,這意味着將發送 1,000 個插入命令到數據庫。

EFBatchOperation 還具有進行批量更新和批量刪除的方法,對其中的每個來說,好消息是:您不必像在 EF 中一樣事先加載實體到內存或上下文。 相反,這里有一個如何使用 EFBatchOperation 從數據庫刪除選擇行的示例:

 
EFBatchOperation.For(context, context.BusinessEntityContacts).Where(
  p => p.ContactTypeId == 11).Delete();

它發送相關的 SQL 到數據庫:

 
DELETE FROM [Person].[BusinessEntityContact] WHERE 11 = [ContactTypeID]

批量操作命令已經提供了顯著的性能提升,現在 Eliasson 正致力於研究 DbContext.Include 方法的替代方案,以提升預先加載的性能。 EF 實用程序中方法的目標是“轉為將每一個‘已包括’集合加載為單獨查詢,然后手動修復這些關系。 同時還提供子集合篩選、排序和分頁(如有可能的話)。”,而不是平鋪數據或將資源浪費在結果中的大量冗余數據上。您可以詳細了解此功能,並可在 bit.ly/1hBsGf5 上密切關注其發展。 請不要忽視此項目的 readme.md 文件。

Entity Framework 6 Contrib

Entity Framework 6 Contrib 是由 Microsoft MVP Unai Zorrilla 在 CodePlex 上開展的項目 (ef6contrib.codeplex.com)。 Zorrilla 已經向 Microsoft EF 程序包發布了多項內容,例如“自定義復數化”、AddRange 和 RemoveRange 以及 AddFrom­Assembly,我已在之前的專欄或文章中撰寫了所有這些功能。 Zorrilla 擁有在 ef6contrib.codeplex.com 網站上維護的少數額外幫助程序,包括:

  • 預配置的西班牙語復數化服務(這已合並到我之前討論的 EntityFramework Reverse POCO Code First 生成器項目中)。
  • 可在運行時將 Fluent API 配置添加到 Code First 模型的兩個更加便捷的方法。
  • 不包含在 EF 中的、可以與 Code First 遷移一起使用的一些操作,例如 DatabaseCollation、GrantTablePermission 和 RevokeTablePermission。
  • 一個適用於遷移的稱為 DropAndMigrateDatabaseToLatestVersion 的初始化表達式。
  • 一組利用 EF6 偵聽器和依賴關系解析程序的查詢分析器類型。

我一直非常喜愛 Zorrilla 對 EF 的新增功能的原因在於,他在工作中采用自己編寫的代碼,反復使用,並將其封裝與他人分享。 尤其是分析器,非常酷。 您可以設置參數,通過參數您可以衡量 EF 數據庫執行的性能,監視代碼與您期望的符合程度。 還有一個分析器可檢查非參數化查詢。 如果您將偵聽器添加到 DbConfiguration 類(另一個 EF6 功能),它將分析來自給定 DbContext 的所有命令。 CodePlex 項目有大量讓您研究分析器的測試和示例,以及包含在 Entity Framework 6 Contrib 中的其他工具。 圖 3 顯示添加 PerformanceInterceptor 的示例中的一個 DbConfiguration 類,然后指定其在集合中檢查四個分析器中的三個。

圖 3 從 Entity Framework 6 Contrib 配置分析器

 
public class Configuration : DbConfiguration  {
    public Configuration() {
      this.AddDependencyResolver(new CustomResolver());
      this.AddInterceptor(new PerformanceInterceptor((msg =>
      {
        Console.WriteLine(msg.Message);
      })));
    }
    private class CustomResolver : IDbDependencyResolver{
      public object GetService(Type type, object key) {
        return null;
      }
      public IEnumerable<object> GetServices(Type type, object key) {
        // You can use here your preferred IoC container
        if (typeof(IPerformanceAnalyzer).IsAssignableFrom(type)) {
          return new List<IPerformanceAnalyzer>(){
             new ExecutionTimePerformanceAnalyzer(TimeSpan.FromSeconds(3)),
             new UnparametrizedWhereClausesPerformanceAnalyzer(),
             new TopSlowQueriesPerformanceAnalyzer(10)
          };
        }
        return Enumerable.Empty<object>();
      }
    }
  }

根據此配置,控制台窗口將顯示來自分析器的所有報告。

豐富的 EF 擴展和工具

我發現只有一小部分工具對我的工作確實有益。 我希望您沒有忽視其他工具,但在這里我沒有空間來深入介紹所有工具。 Erik Ejlskov Jensen 在他的博客文章中有一個更值得關注的擴展的列表:“Entity Framework 6 (& SQL Server Compact) (5)–Entity Framework 6 Extensions”(bit.ly/SxxPc5)。 該列表包括為 EF6 啟用二級緩存 (bit.ly/UePlmU) 的 EF 緩存提供程序的更新版本、用於替代停止使用的自跟蹤實體 (trackable.codeplex.com) 的可跟蹤實體以及一些解決批量操作功能的其他項目。 Ejlskov Jensen 是 SQL Server CE MVP,除了直接對 EF6 發布了很多強大的 SQL CE 相關功能外,他還發布了一個廣受歡迎的 Visual Studio 擴展 SQL Server Compact Toolbox,其中包括許多功能可幫助使用 EF。 無論您是使用帶 EF 的 SQL CE 還是使用不帶 EF 的 SQL CE,這個工具箱都是一個重要的擴展。 最后,我想向 Jimmy Bogard 在一系列名為“Missing EF Feature Workarounds”(缺失 EF 功能的解決方法)的博客文章中所做的工作致以真誠的感謝,其中還包括將 EF6 擴展為向 EF 模型提供全局篩選器的方法,且可作為 NuGet 程序包提供。 您可以在他的博客文章中了解更多詳細信息,網址為 bit.ly/1prZv0a


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

衷心感謝以下技術專家對本文的審閱:Mikael Eliasson、Simon Hughes 和 Unai Zorrilla


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM