Entity Framework
Entity Framework (又稱ADO.NET Entity Framework) 是微軟以 ADO.NET 為基礎所發展出來的物件關聯對應 (O/R Mapping) 解決方案,早期被稱為 ObjectSpace,包含在 .NET Framework中發表。從版本6開始獨立發佈。
背景
編輯長久以來,程式設計師和資料庫總是保持着一種微妙的關係,在商用應用程式中,資料庫一定是不可或缺的元件,這讓程式設計師一定要為了連接與存取資料庫而去學習 SQL 指令,因此在資訊業中有很多人都在研究如何將程式設計模型和資料庫整合在一起,物件關聯對應 (Object-Relational Mapping) 的技術就是由此而生,像Hibernate或NHibernate都是這個技術下的產物,而微軟雖然有了ADO.NET這個資料存取的利器,但卻沒有像NHibernate這樣的物件對應工具,因此微軟在.NET Framework 2.0發展時期,就提出了一個ObjectSpace的概念,ObjectSpace可以讓應用程式可以用完全物件化的方法連接與存取資料庫,其技術概念與NHibernate相當類似,然而ObjectSpace工程相當大,在.NET Framework 2.0完成時仍無法全部完成,因此微軟將ObjectSpace納入下一版本的.NET Framework中,並且再加上一個設計的工具(Designer),構成了現在的 ADO.NET Entity Framework。
Entity Framework是ADO.NET之上支援面向數據應用程式開發,使得開發者工作於領域相關的對象和屬性的數據級,如客戶、客戶地址等,不必關注儲存數據的底層表、列。這種在更高層次上建立、維護面向數據的應用程式可以大大節約編碼量。[3]
Entity Framework 利用了抽象化資料結構的方式,將每個資料庫物件都轉換成應用程式物件 (entity),而資料欄位都轉換為屬性 (property),關聯則轉換為結合屬性 (association),讓資料庫的 E/R 模型完全的轉成物件模型,如此讓程式設計師能用最熟悉的程式語言來呼叫存取。而在抽象化的結構之下,則是高度整合與對應結構的概念層、對應層和儲存層,以及支援 Entity Framework 的資料提供者 (provider),讓資料存取的工作得以順利與完整的進行。
- 概念層:負責向上的物件與屬性顯露與存取。
- 對應層:將上方的概念層和底下的儲存層的資料結構對應在一起。
- 儲存層:依不同資料庫與資料結構,而顯露出實體的資料結構體,和 Provider 一起,負責實際對資料庫的存取和 SQL 的產生。
歷史
編輯2008年8月11日,Entity Framework的第一版(EFv1)隨.NET Framework 3.5 Service Pack 1和Visual Studio 2008 Service Pack 1發佈。該版受到了廣泛的批評。[4]
2010年4月12日,Entity Framework第2版,稱為Entity Framework 4.0 (EFv4)發佈,解決了第一版的很多問題。[5]該版本完全包含在.NET Framework中。
2011年4月12日發佈了Entity Framework第3個版本,稱為version 4.1,開始支援Code First。2011年7月25日發佈了Entity Framework 4.1 Update 1。
2012年2月29日發佈了version 4.3.1。[6]
2012年8月11日發佈了Version 5.0.0。[7]與.NET framework 4.5配套。
2013年10月17日發佈了Version 6.0。[8]並成為開源軟件,使用Apache License v2. 類似於ASP.NET MVC,開源發佈於GitHub。[9] This version has a number of improvements for code-first support.[10]Entity Framework 6.0、6.1、6.2、6.3 和 6.4 完全作為NuGet包提供。
2014年5月19日,微軟決定為了讓其.NET能跨平台,下一版Entity Framework將完全重寫。[11]2016年6月27日,發佈了Entity Framework Core 1.0, 伴隨着ASP.NET Core 1.0 和 .NET Core 1.0.[12]本來其命名為Entity Framework 7,但為了突出其是完全重寫而不是替換EF6所以重新命名。[13]
架構
編輯ADO.NET Entity Framework架構,從底向上包括:
- Data source specific providers, ADO.NET抽象介面連接到資料庫。
- Map provider, 特定資料庫的provider,翻譯Entity SQL命令樹到資料庫本地SQL方言查詢。包括Store-specific bridge,負責把一般命令樹翻譯為儲存特定的命令樹。
- EDM parser and view mapping, 把數據模型的特定的SDL規範和如何對映到關係模型。從關係模式角度,它建立了對應於概念模型的數據views。它聚合(aggregate)多張表的資訊成為一個實體(entity),把一個到實體的修改(update)分割為到多個表的修改。
- Query and update pipeline, 處理查詢、過濾器、修改等請求,轉化為經典命令樹。
- Metadata services, 處理實體、關係、對映的所有元數據。
- Transactions, 整合基礎儲存的事務能力。如果基礎儲存不支援事務,則在這個層次上實現事務。
- Conceptual layer API, 提供了概念模式下的編程介面。遵從ADO.NET模式,使用Connection對象參照map provider, 使用Command對象傳送查詢,返回EntityResultSets 或 EntitySets 以包含結果。
- Disconnected components, ADO.NET Entity Framework使用的本地快取數據集和實體集,在偶爾連接環境。
- Embedded database: ADO.NET Entity Framework包含一個輕量嵌入資料庫用於客戶端快取和查詢關聯式資料庫。
- Design tools, 如Mapping Designer, ADO.NET Entity Framework包含的用於簡化對映從概念模式到關係模式,指出實體類型的哪些屬性對映到資料庫的哪個表。
- Programming layer, 暴露EDM作為編程結構,可被程式語言使用
- Object services, 自動產生CLR類代碼,把同一屬性作為一個實體,允許實體實例作為.NET 對象.
- Web services, 暴露web服務的實體
- High-level services, 如工作在實體上的報告服務。
概念層結構
編輯概念層結構定義了物件模型 (Object Model),讓上層的應用程式碼可以如物件導向的方式般存取資料,概念層結構是由 CSDL (Conceptual Schema Definition Language) 所撰寫[14]。
一份概念層結構定義如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="Employees" Alias="Self" xmlns="http://schemas.microsoft.com/ado/2006/04/edm">
<EntityContainer Name="EmployeesContext">
<EntitySet Name="Employees" EntityType="Employees.Employees" />
</EntityContainer>
<EntityType Name="Employees">
<Key>
<PropertyRef Name="EmployeeId" />
</Key>
<Property Name="EmployeeId" Type="Guid" Nullable="false" />
<Property Name="LastName" Type="String" Nullable="false" />
<Property Name="FirstName" Type="String" Nullable="false" />
<Property Name="Email" Type="String" Nullable="false" />
</EntityType>
</Schema>
對應層結構
編輯對應層結構負責將上層的概念層結構以及下層的儲存體結構中的成員結合在一起,以確認資料的來源與流向。對應層結構是由 MSL (Mapping Specification Language) 所撰寫[15]。
一份對應層結構定義如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Mapping Space="C-S" xmlns="urn:schemas-microsoft-com:windows:storage:mapping:CS">
<EntityContainerMapping StorageEntityContainer="dbo" CdmEntityContainer="EmployeesContext">
<EntitySetMapping Name="Employees" StoreEntitySet="Employees" TypeName="Employees.Employees">
<ScalarProperty Name="EmployeeId" ColumnName="EmployeeId" />
<ScalarProperty Name="LastName" ColumnName="LastName" />
<ScalarProperty Name="FirstName" ColumnName="FirstName" />
<ScalarProperty Name="Email" ColumnName="Email" />
</EntitySetMapping>
</EntityContainerMapping>
</Mapping>
儲存層結構
編輯儲存層結構是負責與資料庫管理系統(DBMS)中的資料表做實體對應 (Physical Mapping),讓資料可以輸入正確的資料來源中,或者由正確的資料來源取出。它是由 SSDL (Storage Schema Definition Language) 所撰寫[16]。
一份儲存層結構定義如下所示:
<?xml version="1.0" encoding="utf-8"?>
<Schema Namespace="Employees.Store" Alias="Self"
Provider="System.Data.SqlClient"
ProviderManifestToken="2005"
xmlns="http://schemas.microsoft.com/ado/2006/04/edm/ssdl">
<EntityContainer Name="dbo">
<EntitySet Name="Employees" EntityType="Employees.Store.Employees" />
</EntityContainer>
<EntityType Name="Employees">
<Key>
<PropertyRef Name="EmployeeId" />
</Key>
<Property Name="EmployeeId" Type="uniqueidentifier" Nullable="false" />
<Property Name="LastName" Type="nvarchar" Nullable="false" MaxLength="50" />
<Property Name="FirstName" Type="nvarchar" Nullable="false" />
<Property Name="Email" Type="nvarchar" Nullable="false" />
</EntityType>
</Schema>
Entity Data Model
編輯Entity Data Model (EDM) 給出數據的概念模型(CSDL) ,這所使用的建模技術被稱為Entity Data Model, 是實體-關係模型的擴充版。[17]數據模型主要描述了實體和其涉及的關聯(Association)。EDM模式用Schema Definition Language (SDL)表述,這事XML的一種應用。此外,從概念模式(CSDL)到儲存模式(SSDL)的對映(MSL)也必須用XML表示。[18]
Visual Studio提供了Entity Designer 視覺化建立EDM和對映規範。該工具輸出XML檔案(*.edmx)來描述這種模式和對映。Edmx檔案包含EF元數據(CSDL/MSL/SSDL內容)。也可手工編輯這3個檔案(csdl, msl, ssdl)。
Mapping
編輯Visual Studio的Entity Data Model Wizard[19]在大部分情況下最初產生資料庫模式和概念模式的1對1對映。關係模式下,表和主鍵、外來鍵組成元素。「實體類型」定義了概念模式下的數據。
實體類型是多個類型欄位的聚合,每個欄位對映到資料庫的特定列,可以包含來自多個物理表的資訊。實體類型可以彼此有關係,且獨立於物理模式內的關係。相關的實體可以通過欄位的名字表示這種關係,以代替從資料庫的列取得值,通過這種欄位可以遍歷相關的實體,返回一個實體或實體集合。
實體類型形成了對象的類,實體是整個類型的實例。實體是應用程式的單個對象,用一個鍵索引。
ADO.NET Entity Framework使用Entity Data Model (EDM)表示這種對映。
ADO.NET Entity Framework使用eSQL,SQL的一個衍生,來執行查詢、集合論操作、修改實體及其關係。[20]
實體
編輯實體是「實體類型」的實例,表示單個對象的實例(如「客戶」、「訂單」)。ADO.NET Entity Framework中的實體屬性是完全類型化的,完全相容於DBMS的型別系統和.NET Framework的Common Type System。屬性可以是SimpleType或ComplexType或多值的。所有EntityType屬於某個命名空間,並包含一個EntityKey屬性。
所有實體實例在EntityContainers中。每個專案有一個或多個EntityContainers。
EDM 類型 | CLR 類型對映 |
---|---|
Edm.Binary | Byte[] |
Edm.Boolean | Boolean |
Edm.Byte | Byte |
Edm.DateTime | DateTime |
Edm.DateTimeOffset | DateTimeOffset |
Edm.Decimal | Decimal |
Edm.Double | Double |
Edm.Guid | Guid |
Edm.Int16 | Int16 |
Edm.Int32 | Int32 |
Edm.Int64 | Int64 |
Edm.SByte | SByte |
Edm.Single | Single |
Edm.String | String |
Edm.Time | TimeSpan |
關係
編輯任何兩個實體類型可以是相關的,或者是Association關係或者Containment關係。用Relationship Type來表示。
關係類型用degree (arity)和multiplicity刻畫。ADO.NET Entity Framework支援二元雙向關係,multiplicity包括一對一、一對多、多對多。實體間的關係是有名的,稱為Role。定義了關係的目的。
關係類型可以有Operation或Action。例如,刪除一個實體,其關聯的關係可以採取:
- Cascade:刪除關係實例和所有相關聯的實體實例。
- None.
模式定義語言
編輯ADO.NET Entity Framework使用基於XML的數據定義語言稱為 Schema Definition Language (SDL)定義EDM Schema。SDL定義了SimpleTypes類似於CTS基礎類型,包括String, Int32, Double, Decimal, Guid, 和 DateTime等等。列舉類型定義了基礎值和其名字的對映,也被認為是簡單類型。ComplexTypes為其他類型的聚合。屬性的集合定義了實體類型。寫為巴恩斯瑙爾範式:
EntityType ::=
ENTITYTYPE entityTypeName [BASE entityTypeName]
[ABSTRACT true|false] KEY propertyName [, propertyName]*
{(propertyName PropertyType [PropertyFacet]*) +}
PropertyType ::= (
(PrimitiveType [PrimitiveTypeFacets]*)
| (complexTypeName)
| RowType
PropertyFacet ::= (
[NULLABLE true | false]
| [DEFAULT defaultVal]
| [MULTIPLICITY [1|*]]
)
PropertyTypeFacet ::=
MAXLENGTH | PRECISION | SCALE
| UNICODE | FIXEDLENGTH | COLLATION
| DATETIMEKIND | PRESERVESECONDS
PrimitiveType ::=
BINARY | STRING | BOOLEAN
| SINGLE | DOUBLE | DECIMAL | GUID
| BYTE | SBYTE | INT16 | INT32 | INT64
| DATETIME | DATETIMEOFFSET | TIME
)
Facets用於描述屬性的元數據,如是否為可空、預設值、為單值或多值。
<ComplexType Name="Addr">
<Property Name="Street" Type="String" Nullable="false" />
<Property Name="City" Type="String" Nullable="false" />
<Property Name="Country" Type="String" Nullable="false" />
<Property Name="PostalCode" Type="Int32" />
</ComplexType>
<EntityType Name="Customer">
<Key>
<PropertyRef Name="Email" />
</Key>
<Property Name="Name" Type="String" />
<Property Name="Email" Type="String" Nullable="false" />
<Property Name="Address" Type="Addr" />
</EntityType>
關係類型,如客戶和訂單是1對多關係。
<Association Name="CustomerAndOrders">
<End Type="Customer" Multiplicity="1" />
<End Type="Orders" Multiplicity="*">
<OnDelete Action="Cascade" />
</End>
</Association>
查詢物件
編輯ADO.NET 實體資料模型工具會產生從 ObjectContext (代表概念模型中所定義的實體容器) 衍生而來的類別。 ObjectContext 類別支援針對將實體當成物件傳回之概念模型進行查詢,也支援建立、更新和刪除實體物件。 Entity Framework 支援針對概念模型進行物件查詢。 這些查詢可以使用 Entity SQL 、Language-Integrated Query (LINQ) 和物件查詢產生器方法來撰寫。[23]
Entity SQL
編輯Entity Client 是 ADO.NET Entity Framework 中的原生用戶端 (Native Client)。它的物件模型和 ADO.NET 的其他用戶端非常相似,一樣有 Connection, Command, DataReader 等物件,但最大的差異就是,它有自己的 SQL 指令 (Entity SQL),可以用 SQL 的方式存取 EDM。但沒有明確的joins。簡單的說,就是把 EDM 當成一個實體資料庫。
查詢管線分析Entity SQL查詢為一棵命令樹, query into a command tree, 分開多個表上的查詢,再移交EntityClient provider。EntityClient provider使用Connection對象初始化。EntityClient provider再把Entity SQL命令樹轉化為資料庫的本地SQL查詢。查詢返回Entity SQL ResultSet,但不限於一個表的結果。
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder = new EntityConnectionStringBuilder();
// Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = @"res://*/AdventureWorksModel.csdl|
res://*/AdventureWorksModel.ssdl|
res://*/AdventureWorksModel.msl";
Console.WriteLine(entityBuilder.ToString());
using (EntityConnection conn = new EntityConnection(entityBuilder.ToString()))
{
conn.Open();
Console.WriteLine("Just testing the connection.");
conn.Close();
}
Entity SQL經典函數
編輯Entity Framework相容的data providers都支援的函數,可用於Entity SQL查詢。LINQ to Entities的大部門擴充方法都翻譯為經典函數。ADO.NET data provider會把經典函數翻譯為期望的SQL陳述式。
類別 | 經典函數[24] |
---|---|
聚類函數 | Avg, BigCount, Count, Max, Min, StDev, StDevP, Sum, Var, VarP |
數學函數 | Abs, Ceiling, Floor, Power, Round, Truncate |
字串函數 | Concat, Contains, EndsWith, IndexOf, Left, Length, LTrim, Replace, Reverse, Right, RTrim, Substring, StartsWith, ToLower, ToUpper, Trim |
日期時間函數 | AddMicroseconds, AddMilliseconds, AddSeconds, AddMinutes, AddHours, AddNanoseconds, AddDays, AddYears, CreateDateTime, AddMonths, CreateDateTimeOffset, CreateTime, CurrentDateTime, CurrentDateTimeOffset, CurrentUtcDateTime, Day, DayOfYear, DiffNanoseconds, DiffMilliseconds, DiffMicroseconds, DiffSeconds, DiffMinutes, DiffHours, DiffDays, DiffMonths, DiffYears, GetTotalOffsetMinutes, Hour, Millisecond, Minute, Month, Second, TruncateTime, Year |
Bitwise 函數 | BitWiseAnd, BitWiseNot, BitWiseOr, BitWiseXor |
其他函數 | NewGuid |
LINQ to Entities
編輯實作 IEnumerable<T> 泛型介面或 IQueryable<T> 泛型介面的資料來源可以透過 LINQ 進行查詢。 實作泛型 IQueryable<T> 介面之泛型 ObjectQuery<T> 類別的執行個體會當做 LINQ to Entities 查詢的資料來源。 ObjectQuery<T> 泛型類別表示傳回零個或多個具型別物件之集合的查詢。 使用 C# 的 var 關鍵字 (在 Visual Basic 中為 Dim),您也可以讓編譯器推斷實體類型。[25]
using (AdventureWorksEntities AWEntities = new AdventureWorksEntities())
{
ObjectQuery<Product> products = AWEntities.Products;
// LINQ Query syntax:
IOrderedQueryable<Product> query =
from product in products
orderby product.Name, product.ListPrice descending
select product;
// LINQ Method syntax:
IOrderedQueryable<Product> query = products
.OrderBy(product => product.Name)
.ThenByDescending(product => product.ListPrice);
}
查詢產生器方法
編輯ObjectQuery 類別支援對概念模型進行 LINQ to Entities 和 Entity SQL 查詢。 ObjectQuery 也會實作一組查詢產生器方法,這些方法可用來循序建構與 Entity SQL 相等的查詢命令。由於 ObjectQuery 會實作 IQueryable 和 IEnumerable,所以將 ObjectQuery 所實作的查詢產生器方法結合 LINQ 特定的標準查詢運算子方法 (如 First 或 Count) 是可行的。 LINQ 運算子並不會傳回 ObjectQuery,與查詢產生器方法不同。[26]
// Get the contacts with the specified name.
ObjectQuery<Contact> contactQuery = context.Contact
.Where("it.LastName = @ln AND it.FirstName = @fn",
new ObjectParameter("ln", lastName),
new ObjectParameter("fn", firstName));
開發工具
編輯目前 ADO.NET Entity Framework 的開發,在 Visual Studio 2008 中有充分的支援,在安裝 Visual Studio 2008 Service Pack 1 後,檔案範本中即會出現 ADO.NET 實體資料模型 (ADO.NET Entity Data Model) 可讓開發人員利用 Entity Model Designer 來設計 EDM,EDM 亦可由Windows記事本等文字編輯器所編輯。
衍生服務
編輯微軟特別針對了網絡上各種不同的應用程式(例如 AJAX,Silverlight,Mashup 應用程式)開發了一個基於 ADO.NET Entity Framework 之上的服務,稱為 ADO.NET Data Services(專案代號為 Astoria),並與 ADO.NET Entity Framework 一起包裝在 .NET Framework 3.5 Service Pack 1 中發表。
支援廠商
編輯目前已有數個資料庫廠商或元件開發商宣佈要支援 ADO.NET Entity Framework[27]:
- Mircosoft,支援MsSQL.
- Core Lab,支援Oracle、MySQL、PostgreSQL 與 SQLite 資料庫。
- IBM,實作 DB2 使用的 LINQ Provider。
- MySQL,發展 MySQL Server 所用的 Provider。
- Npqsql,發展 PostgreSQL 所用的 Provider。
- OpenLink Software,發展支援多種資料庫所用的 Provider。
- Phoenix Software International,發展支援 SQLite 資料庫的 Provider。
- Sybase,將支援 Anywhere 資料庫。
- VistaDB Software,將支援 VistaDB 資料庫。
- DataDirect Technologies,發展支援多種資料庫所用的 Provider。
- Firebird,支援 Firebird 資料庫。
參考資料
編輯- ^ Release 6.4.4. 2020年5月14日 [2020年5月19日].
- ^ Release 8.0.2. 2024年2月13日 [2024年2月19日].
- ^ Entity Framework Overview - ADO.NET. [2022-06-19]. (原始內容存檔於2022-04-11).
- ^ ADO .NET Entity Framework Vote of No Confidence. [2022-06-18]. (原始內容存檔於2020-10-26).
- ^ Update on the Entity Framework in .NET 4 and Visual Studio 2010. ADO.NET team blog. May 11, 2009 [November 1, 2011]. (原始內容存檔於January 20, 2010).
- ^ EF4.3.1 and EF5 Beta 1 Available on NuGet. ADO.NET team blog. February 29, 2012 [March 27, 2012]. (原始內容存檔於March 25, 2012).
- ^ EF5 Available on CodePlex. August 11, 2012 [2022-06-18]. (原始內容存檔於2017-09-07).
- ^ EF6 RTM Available. October 17, 2013. (原始內容存檔於2014-03-30).
- ^ Entity Framework - Home. September 14, 2016 [2022-06-18]. (原始內容存檔於2019-01-10).
- ^ EF Version History. [2022-06-18]. (原始內容存檔於2016-08-04).
- ^ EF7 - New Platforms, New Data Stores. May 19, 2014. (原始內容存檔於2015-09-29).
- ^ Entity Framework Core 1.0.0 Available. 27 June 2016 [2022-06-18]. (原始內容存檔於2019-01-12).
- ^ Hanselman, Scott. ASP.NET 5 is dead - Introducing ASP.NET Core 1.0 and .NET Core 1.0 - Scott Hanselman. www.hanselman.com. [2016-07-11]. (原始內容存檔於2016-01-20).
- ^ Schemas and Mappings Specification: CSDL. [2008-10-02]. (原始內容存檔於2008-12-12).
- ^ Schemas and Mappings Specification: MSL. [2008-10-02]. (原始內容存檔於2008-09-14).
- ^ Schemas and Mappings Specification: SSDL. [2008-10-02]. (原始內容存檔於2008-12-29).
- ^ Entity Data Model. MSDN, Microsoft. August 2, 2012 [August 15, 2013]. (原始內容存檔於2016-06-03).
- ^ 參照錯誤:沒有為名為
CsdlMslSsdl
的參考文獻提供內容 - ^ 參照錯誤:沒有為名為
EdmWizard
的參考文獻提供內容 - ^ Kogent Solutions Inc., ASP.NET 3.5 Black Book, Dreamtech Press, 2009, ISBN 978-81-7722-831-1
- ^ 參照錯誤:沒有為名為
SimpleTypes
的參考文獻提供內容 - ^ 參照錯誤:沒有為名為
ConceptualModelTypes
的參考文獻提供內容 - ^ 處理實體資料. [2014-10-12]. (原始內容存檔於2014-10-18).
- ^ 參照錯誤:沒有為名為
MsdnCanonicalFunctions
的參考文獻提供內容 - ^ LINQ to Entities 中的查詢. [2014-12-12]. (原始內容存檔於2014-10-22).
- ^ 查詢產生器方法 (Entity Framework). [2014-10-12]. (原始內容存檔於2014-10-18).
- ^ Microsoft Simplifies Data-Centric Development in Heterogeneous IT Environments. [2008-10-01]. (原始內容存檔於2008-12-10).
外部連結
編輯- (英文) MSDN Library : ADO.NET Entity Framework(頁面存檔備份,存於互聯網檔案館)
- (繁體中文) 讀寫 ADO.NET Entity Framework(頁面存檔備份,存於互聯網檔案館)
- (繁體中文) 整合 ADO.NET Entity Framework 到應用程式中(頁面存檔備份,存於互聯網檔案館)
- (繁體中文) 首次接觸 ADO.NET Entity Framework(頁面存檔備份,存於互聯網檔案館)
- (繁體中文) ADO.NET Entity Framework 概觀(頁面存檔備份,存於互聯網檔案館)
- (英文) Recent ADO.NET Entity Framework provider news - Demos and downloads