ADO.NET

ADO.NET是微軟在.NET Framework中負責資料存取的類別庫集，它是使用在COM時代奠基的OLE DB技術以及.NET Framework的類別庫和程式語言來發展的，它可以讓.NET上的任何程式語言能夠連接並存取關聯式資料庫與非資料庫型資料來源（例如XML，Excel或是文字檔資料），或是獨立出來作為處理應用程式資料的類別物件，其在.NET Framework中的地位是舉足輕重，許多人將ADO.NET視為 ActiveX Data Objects (ADO) 的下一個版本，但其實它是一個全新的架構、產品與概念。

ADO.NET類封裝在System.Data.dll中，並且與System.Xml.dll中的XML類集成。

## 歷史

### 發展緣起

在1990年代初期，微軟已經開發了許多的資料存取方式，像是ODBC架構、和Microsoft Access資料庫交互使用的DAO物件、可以跨越網路存取資料的Remote Data Object以及讓DAO元件可以存取ODBC資料來源的ODBCDirect技術等等，技術雖然多，但是卻又各自為政，而且每個技術的重疊性也很高（像是ODBC有Microsoft Access的驅動程式）；RDO雖然可跨網路，但是ODBC的驅動程式中也有提供跨網路的功能（像是SQL Server和Oracle驅動程式），如此琳琅滿目重疊性又高的技術群，讓企業與開發人員在選擇、學習與應用上產生了很多的困難。

1996年，適逢COM的出現，微軟將資料存取的核心開始改寫為以COM為基礎的OLE DB，並且在它上面建立一個新的統一的資料存取的高層對象模型－ADO。ADO推出後順利的取代了DAO和RDO，成為在Windows NT 4.0和Windows 2000作業系統上開發資料庫應用程式的首選。它將OLE DB的物件模型進一步簡化；由資料庫廠商開發滿足OLE DB接口的資料提供者（data provider，這個模式在此時奠基），而ADO本身則是與資料來源無關（data source independent）的對象結構，讓它迅速的獲得了使用ASP、Visual Basic、COM的開發人員的青睞。它能夠順利取代DAO與RDO，要關鍵在於ADO的與資料庫伺服器端/客戶端的特性無關，這使得ADO通用性極好。然而ADO本身的架構仍然有缺陷（尤其是在開發網路應用程式時，最好的例子就是Recordset無法離線），這也是微軟為何不在.NET Framework中繼續使用ADO的主要原因。

1998年時，微軟提出了一個下一代的應用程式開發框架（Application Framework）的計畫，計畫中包含了：

- ASP+：改良與重新設計ASP技術，強化它的Web應用程式發展能力。
- Storage+：發展新的資料庫與物件導向之檔案系統結構（用於SQL Server 8.0（即後來的SQL Server 2000）與NTFS），以及發展新一代的資料存取元件，並改良ADO本身的缺陷，讓它更能夠成為應用程式資料存取的核心功能。
- COM+：改良COM和MTS，成為企業級應用程式開發的基礎元件。

ADO+即為Storage+的一支。

### ADO.NET的前身：ADO+

1998年起，因為Web應用程式的竄起，大大改變了許多應用程式的設計方式，傳統的資料庫連線保存設計法無法適用於此類應用程式，這讓ADO應用程式遇到了很大的瓶頸，也讓微軟開始思考讓資料集（Resultset，在ADO中稱為Recordset）能夠離線化的能力，以及能在使用者端建立一個小型資料庫的概念，這個概念就是ADO.NET中離線型資料模型（disconnected data model）的基礎，而在ADO的使用情形來看，資料庫連線以及資源耗用的情形較嚴重（像是Server-side cursor或是Recordset.Open會保持連線狀態），在ADO.NET中也改良了這些物件，構成了能夠減少資料庫連線和資源使用量的功能。XML的使用也是這個版本的重要發展之一。

2000年，微軟的Microsoft .NET計畫開始成形，許多的微軟產品都冠上.NET的標籤，ADO+也不例外，改名為ADO.NET，並包裝到.NET Framework類別庫中，成為.NET平台中唯一的資料存取元件。

## 架構

ADO.NET由連線資料來源（connected data source）以及離線資料模型（disconnected data model）兩個部份構成，這兩個部份是相輔相成的。

### 連線資料來源

若沒辦法連線到資料庫，則無法被稱為資料存取元件。連線資料來源便是用來連接資料庫（或是具有OLE DB資料來源提供者）的物件類別，由下列接口構成：

- IDbConnection，負責與資料庫的連線管理，包含連線字串（connection string），連線的開關，資料庫交易的啟始與連線錯誤的處理，所有的ADO.NET資料提供者都要實作此介面。
- `Open()/Close()`：開啟與關閉資料庫連線。
- `BeginTransaction()`：啟動資料庫交易，並回傳一個`IDbTransaction`物件，以控制交易的結果。
- IDbCommand，負責執行資料庫指令（在大多數的案例中都是SQL指令），並傳回由資料庫中擷取的結果集，或是執行不回傳結果集的資料庫指令。
- `ExecuteNonQuery()`：執行不回傳結果集的資料庫指令，像是`INSERT`、`UPDATE`與`DELETE`指令，返回值為該命令所影響的行數。對於其他所有類型的語句，返回值 為 -1。
- `ExecuteScalar()`：執行指令並回傳第一列第一行中的值（object類型）。當沒有數據時，ExcuteScalar方法返回System.DBNull。
- `ExecuteReader()`：執行指令並回傳IDataReader物件，以讀取資料集中的資料。
- `BeginExecuteNonQuery`：開始執行異步查詢
- `EndExecuteNonQuery`: 結束執行異步查詢
- IDataParameter，負責裝載資料庫指令所需要的參數資料，在使用參數化查詢時會經常使用。對於不同的數據源來說，占位符不同。SQLServer數據源用@parametername格式來命名參數，OleDb以及Odbc數據源均用問號（?）來標識參數位置，而Oracle則以:parmname格式使用命名參數。
- IDbTransaction，負責裝載資料庫交易所需的控制物件，以執行交易的認可（commit）或撤銷（rollback）的工作。
- `Commit()`：認可資料庫交易。
- `Rollback()`：撤銷資料庫交易。
- IDbDataAdapter，負責將來自於IDbCommand執行取得的結果集，裝載到離線型資料集（DataSet）或是離線型資料表（DataTable）中。
- `Fill()`：將資料填入離線型資料物件。
- `Update()`：將變更過的離線型資料物件中的資料寫回資料庫。
- IDataReader，建立一個只可向前讀取游標（forward-only）的資料讀取器工具，以逐列讀取方式存取資料，`IDbDataAdapter`內部也是由它來讀取資料。
- `Read()`：第一次調用Read方法獲取第一行數據，並將游標指向下一行數據。當再次調用該方法時候，將讀取下一行數據。當檢測到不再有數據行時，Read方法將返回`false`。
- IDataRecord，在`IDataReader`讀取資料後實際裝載資料列的物件，提供方法來讀取資料行中的資料，以及轉換成.NET Framework原生型別的工具。
- `GetOrdinal()`：取得指定資料行的欄位索引值。
- `IsDBNull()`：判斷指定欄位的資料是否為NULL值。

使用連線資料來源需要由開發人員自我管理連線，並且直接操作資料存取的相關細節，但它的優點是速度快，而且可以自訂整個資料存取流程的邏輯。

### ADO.NET資料提供者(Data Provider)

在.NET Framework中，ADO.NET預設提供了四種資料來源：

- SQL Server：由System.Data.SqlClient提供原生資料來源，是微軟官方建議存取SQL Server時建議使用的資料提供者。以Sql為字首的類別群
- OLE DB Data Source：由System.Data.OleDb提供支援，可適用於OLE DB Provider for ODBC以外的OLE DB資料提供者。以OleDb為字首的類別群。支持本地事務和分布式事務。對於分布式事務，默認情況下，用於 OLE DB 的 .NET Framework 數據提供程序會自動登記在事務中，並自動從 Windows 2000 組件服務獲取事務詳細資訊。
- Oracle：由System.Data.OracleClient提供支援，但使用者的電腦必須安裝Oracle Client 8.1.7或更新版本才行（.NET Framework 1.1開始支援）。以Oracle為字首的類別群。必須同時引用 System.Data和 System.Data.OracleClient。
- ODBC：補OLE DB Provider for ODBC的支援，由System.Data.Odbc提供支援（.NET Framework 1.1開始支援）。以Odbc為字首的類別群
- EntityClient實體數據模型(EDM)應用程式的數據訪問。使用 System.Data.EntityClient 命名空間。

其他廠商亦為不同的資料庫提供資料來源：

- DataDirect Technologies發行100%列管提供源，支援主流企業資料庫（Oracle, Sybase, DB2, SQL Server, Progress RDBMS）
- OpenLink Software給大量的客戶指定資料庫發行提供源，包括到其他資料存取機構的橋接提供源，並可以在視窗下微軟自己或者Mono的CLR實做下支援。
- MySQL為本身的MySQL Database Server提供了ADO.NET的原生資料提供者。
- Oracle自行開發的.NET Data Provider。

對每種Data Provider，ADO.NET要實現下述對象結構：

- Connection 對象提供與數據源的連接。
- Command對象使您能夠訪問用於返回數據、修改數據、運行存儲過程以及發送或檢索參數資訊的資料庫命令。
- DataReader 對象從數據源中提供快速的，只讀的數據流。
- DataAdapter 對象提供連接 DataSet 對象和數據源的橋梁。DataAdapter 使用 Command 對象在數據源中執行 SQL 命令，以便將數據加載到 DataSet 中，並使對 DataSet 中數據的更改與數據源保持一致。
- Parameter 對象用於參數化查詢。

例如，對於SQL Server數據源：

```C#
strSQL = "SELECT * FROM users WHERE Name = @Name and Password = @Password";
SqlParamter[] paras = new SqlParamter[]{//参数数组
     new SqlParamter("@Name",SqlDBType.Varchar,50)
     new SqlParamter("@Password",SqlDBType.Varchar,50)};
paras[0].value = userName;//绑定用户名
paras[1].value = password;//绑定用户密码
```

- ConnectionStringBuilder：提供一種用於創建和管理由 Connection 對象使用的連接字串的內容的簡單方法。所有 ConnectionStringBuilder 對象的基類均為 DbConnectionStringBuilder 類。
- CommandBuilder：自動生成 DataAdapter 的命令屬性或從存儲過程中派生參數資訊，並填充 Command 對象的 Parameters 集合。所有 CommandBuilder 對象的基類均為 DbCommandBuilder 類。

### 離線資料模型

離線資料模型是微軟為了改良ADO在網路應用程式中的缺陷所設計的，同時它也是COM+中，IMDB技術的設計概念的實作品，但它並沒有完整的IMDB功能，像是交易處理（transaction processing），但它仍不失為一個能在離線狀態下處理資料的好幫手，它也可以透過連線資料來源物件，支援將離線資料存回資料庫的能力。離線資料模型由下列物件組成：

- DataSet，離線型資料模型的核心之一，可將它當成一個離線型的資料庫，它可以內含許多個DataTable，並且利用關聯與限制方式來設定資料的完整性，它本身也提供了可以和XML交互作業的支援。
- `ReadXml()/WriteXml()`：以DataSet的結構讀寫XML。
- `ReadXmlSchema()/WriteXmlSchema()`：以DataSet的結構讀寫XML Schema。
- `GetXml()/GetXmlSchema()`：取得DataSet內容的XML或XML Schema。
- `Merge()`：合併兩個DataSet。
- `Load()`：自`IDataReader`載入資料到DataSet。
- `AcceptChanges()`：將修改過的資料列的修改旗標改為`Unchanged`。
- `GetChanges()`：將修改過的資料列以DataRow陣列方式傳回。
- `RejectChanges()`：撤銷所有資料的修改。
- DataTable，離線型資料模型的核心之一，可將它當成一個離線型的資料表，是儲存資料的收納器。
- `Copy()`：將DataTable複製出一個副本，包含結構與資料。
- `Merge()`：將兩個DataTable合併。
- `Select()`：以指定的特殊查詢語法，傳回符合條件的DataRow陣列。
- `Compute()`：以指定的彙總語法，傳回彙總的結果。
- `GetErrors()`：傳回有錯誤的DataRow陣列。
- `HasErrors`：判斷DataTable中的DataRow有沒有含有錯誤的DataRow。
- DataRow，表示表格中的資料列，與資料欄組合成資料儲存的單元。
- `IsNull()`：判斷指定的欄位是否為NULL值。
- `ItemArray`：將DataRow中的資料轉換成陣列。
- DataColumn，表示表格中的欄位。
- DataView，展示資料的輔助元件，類似於資料庫中的檢視表，並可設定過濾條件與排序條件。
- `Filter`：設定DataView的過濾條件。
- `Sort`：設定DataView的排序條件。
- `ToTable()`：將套用過濾與排序後的內容轉換為DataTable物件。
- DataRelation，可在DataTable之間設定欄位間的關聯。
- Constraint，設定欄位的條件約束，例如`ForeignKeyConstraint`為外部鍵限制，而`UniqueConstraint`則確保了欄位中的值都是唯一的。

DataSet和DataTable除了資料庫的處理以外，也經常被用來管理應用程式中的資料，並且由於它可以儲存在XML中的特性，也讓它可以用來儲存需要保存的應用程式資訊。DataSet中可包含DataRelation對象，用於建構表之間的約束關係。

## 工廠方法

在.NET Framework 1.x的時代，ADO.NET不同的來源有不同的類別搭配（前面已述及），但是若想要在不同的資料來源間搭配，那麼勢必要產生很多的變數來存放不同的資料物件，因此微軟在.NET Framework 2.0中提供了一個`System.Data.Common`命名空間，其中有各種必要物件的共用方法（例如連線是`DbConnection`，命令是`DbCommand`，讀取器是`DbDataReader`，資料配接器是`DbDataAdapter`等），以及`DbProviderFactory`物件，用來總管資料存取的物件。

`DbProviderFactories`則是電腦中所有提供者的總管，開發人員可用`DbProviderFactories.GetFactoryClasses()`取得各個提供者的Invariant Name，再於呼叫`DbProviderFactories.GetFactory()`時傳入指定提供者的Invariant Name即可取得`DbProviderFactory`，再利用下列方法取得共用物件：

- `DbProviderFactory.CreateConnection()`
- `DbProviderFactory.CreateCommand()`
- `DbProviderFactory.CreateParameter()`
- `DbProviderFactory.CreateDataAdapter()`

```csharp
// This example assumes a reference to System.Data.Common.
static DataTable GetProviderFactoryClasses()
{
    // Retrieve the installed providers and factories.
    DataTable table = DbProviderFactories.GetFactoryClasses();

    // Display each row and column value.
    foreach(DataRow row in table.Rows)
    {
        foreach(DataColumn column in table.Columns)
        {
            Console.WriteLine(row[column]);
        }
    }
    return table;
}
```

## XML的整合

XML在ADO.NET中扮演了相當重要的地位，DataSet和DataTable都可以轉換成XML或和XML之間交換資料，在DataTable的內部資料的變更記錄，可以被輸出到一個XML的格式，用來識別變更的情形，這個格式稱為DiffGram，而且它可以直接讀入DataTable之中（使用DataTable.ReadXml並用XmlReadMode.DiffGram當參數）。一個典型的DiffGram如下：

```xml
<diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
  <CustomerDataSet>
    <Customers diffgr:id="Customers1" msdata:rowOrder="0" diffgr:hasChanges="modified">
      <CustomerID>ALFKI</CustomerID>
      <CompanyName>New Company</CompanyName>
    </Customers>
    <Customers diffgr:id="Customers2" msdata:rowOrder="1" diffgram:hasErrors="true">
      <CustomerID>ANATR</CustomerID>
      <CompanyName>Ana Trujillo Emparedados y Helados</CompanyName>
    </Customers>
    <Customers diffgr:id="Customers3" msdata:rowOrder="2">
      <CustomerID>ANTON</CustomerID>
      <CompanyName>Antonio Moreno Taquera</CompanyName>
    </Customers>
    <Customers diffgr:id="Customers4" msdata:rowOrder="3">
      <CustomerID>AROUT</CustomerID>
      <CompanyName>Around the Horn</CompanyName>
    </Customers>
  </CustomerDataSet>
  <diffgr:before>
    <Customers diffgr:id="Customers1" msdata:rowOrder="0">
      <CustomerID>ALFKI</CustomerID>
      <CompanyName>Alfreds Futterkiste</CompanyName>
    </Customers>
  </diffgr:before>
  <diffgr:errors>
    <Customers diffgr:id="Customers2" diffgr:Error="An optimistic concurrency violation has occurred for this row."/>
  </diffgr:errors>
</diffgr:diffgram>
```

DataSet與DataTable也支援直接讀入XML Schema建立結構的能力，以及自行依XML的內容推斷（inference）其結構的能力，下列程式碼為由XML推斷結構的程式：

```csharp
DataSet dataSet = new DataSet();
dataSet.InferXmlSchema9("input_od.xml", new string[] "urn:schemas-microsoft-com:officedata");
```

DataSet和DataTable可以使用XmlDataDocument類別和XML DOM整合在一起，XmlDataDocument的角色就像一個橋接介面，並且作為DataSet和DataTable可使用XPath與XML DOM方式存取的方法。下列程式碼即為使用XmlDataDocument和資料庫中資料轉換為XSLT輸出的範例：

```csharp
// Assumes connection is a valid SqlConnection.
connection.Open();

DataSet custDS = new DataSet("CustomerDataSet");

SqlDataAdapter customerAdapter = new SqlDataAdapter(
  "SELECT * FROM Customers", connection);
customerAdapter.Fill(custDS, "Customers");

SqlDataAdapter orderAdapter = new SqlDataAdapter(
  "SELECT * FROM Orders", connection);
orderAdapter.Fill(custDS, "Orders");

connection.Close();

custDS.Relations.Add("CustOrders",
  custDS.Tables["Customers"].Columns["CustomerID"],
                     custDS.Tables["Orders"].Columns["CustomerID"]).Nested = true;

XmlDataDocument xmlDoc = new XmlDataDocument(custDS); 

XslTransform xslTran = new XslTransform();
xslTran.Load("transform.xsl");

XmlTextWriter writer = new XmlTextWriter("xslt_output.html", 
  System.Text.Encoding.UTF8);

xslTran.Transform(xmlDoc, null, writer);
writer.Close();
```

在.NET Framework中，DataSet被分為兩類，一種是不會強制使用特別型態的DataSet，稱為Untyped DataSet，使用上較方便，但沒有強制的型別限制，另一種則是Typed DataSet，會強制型別，並且是由自訂的XML Schema所產生，Untyped DataSet則沒有XML Schema，由建立時的結構來決定，Typed DataSet可以用Visual Studio，或者是SDK工具中的xsd.exe來產生。

```text
xsd.exe /d /l:CS XSDSchemaFileName.xsd /eld /n:XSDSchema.Namespace
```

產生出來的Typed DataSet會自動將欄位設定成屬性，讓開發人員的存取更方便（這個功能在TableAdapter相當常見）。

```csharp
CustomerDataSet customers = new CustomerDataSet();
SqlDataAdapter adapter = new SqlDataAdapter(
  "SELECT * FROM dbo.Customers;",
  "Data Source=(local);Integrated " +
  "Security=SSPI;Initial Catalog=Northwind");

adapter.Fill(customers, "Customers");

foreach(CustomerDataSet.CustomersRow customerRow in customers.Customers)
  Console.WriteLine(customerRow.CustomerID);
```

## 指令產生器

ADO.NET中有專門用來產生資料處理指令的指令產生器（Command Builder），它可以利用開發人員所指定的`SELECT`指令，自動產生對應的`INSERT`、`UPDATE`與`DELETE`指令，但一開始它並不會自動產生，而是要靠呼叫方法來取得：

- `DbCommandBuilder.GetInsertCommand()`
- `DbCommandBuilder.GetUpdateCommand()`
- `DbCommandBuilder.GetDeleteCommand()`

最常使用到的地方是和DataAdapter並用時，但它要求傳入的`SELECT`語句所選擇的列集合中必須要有主鍵或者唯一鍵，否則無法產生，同時自動產生的指令因為判斷條件很多，對效能可能會有些影響。

## Visual Studio的支援

ADO.NET和Visual Studio開發工具幾乎已經是無縫的整合了，開發人員可以利用Visual Studio來建立強型別（strong-typed）的DataSet，到了Visual Studio 2005時更能夠在Windows Forms應用程式中使用TableAdapter（Typed DataSet和DataAdapter整合的產物）來開發應用程式（不會再看到DataAdapter，但使用上差不多）。Visual Studio在建立Typed DataSet時有提供視覺化介面的支援，以及資料庫組態精靈（Database Configuration Wizard）來讓開發人員以簡單的設定方式來建立DataSet，部分開發人員也將TableAdapter和ASP.NET應用程式的ObjectDataSource控制項並用，亦得到不錯的效果。

在.NET Framework 3.5中，微軟特別為了DataSet和DataTable建立了LINQ Provider（稱為LINQ to DataSet或LINQ to ADO.NET），讓LINQ可以在DataSet或DataTable上使用，可以讓原本在DataSet上的投資（程式碼）得以繼續使用並享有LINQ的便利性。

## ADO.NET和ADO的差異

對於ADO的開發人員來說，最明顯的變化在於以往ADO中的Recordset消失了，並且明確的分開為連線型的DataReader以及離線型的DataSet與DataTable，並且發展支援離線型資料來源的瀏覽工具DataView，這樣的改變，讓習慣使用ADO的VB/ASP開發人員會有某種程度的不習慣，同時讓ADO.NET的學習會較ADO有較些許的複雜性，因此有部分新入門或是VB 6.0/ASP開發人員會在學習.NET Framework或是使用VB.NET開發應用程式時，在.NET Framework中使用ADO來連接資料來源。但在.NET Framework應用程式使用ADO的話，.NET Framework會因為要多一層ADO的COM與VB.NET使用的.NET之間的資料轉換，會讓應用程式效能有少部分的損耗。

下述示例，用ADO讀取一個資料庫中的表格，然後轉為ADO.Net的數據，最後綁定到DataGridView控制項中去顯示：

```vbnet
        Dim cn As ADODB.Connection
        Dim rs As ADODB.Recordset
        cn = New ADODB.Connection
        rs = New ADODB.Recordset
        cn.Provider = "Microsoft.ACE.OLEDB.12.0;"
        cn.ConnectionString = "D:\\budget2016.accdb;"
        cn.Open()

        'check whether the serial num exists in table cutter
        Dim sSQL As String = "SELECT * FROM tPassword" 
        rs.CursorLocation = ADODB.CursorLocationEnum.adUseClient
        rs.Open(sSQL, cn, ADODB.CursorTypeEnum.adOpenKeyset, ADODB.LockTypeEnum.adLockReadOnly,_ 
                 ADODB.CommandTypeEnum.adCmdText)

        Dim da As New System.Data.OleDb.OleDbDataAdapter()
        Dim ds As New DataSet()
        da.Fill(ds, rs, "tPassword")

        'rs.Close()  'Cannot close 
        rs.ActiveConnection = Nothing
        cn.Close()
        rs = Nothing
        cn = Nothing

        DataGridView1.DataSource = (ds.Tables("tPassword"))
```

ADO的RecordSet，相當於在客戶機或伺服器的一個邏輯上的數據表格，使用者可以通過cursor來定位/讀寫當前行，但不能重新對這些行重新排序，也不能對客戶機上的多個RecordSet數據執行跨表的連接（join）查詢。ADO.Net針對上述缺點，在客戶機上實現了DataTable與DataSet，這是客戶機記憶體中的一套（多個）數據表格，可以對其執行各種單表或多表的查詢、修改、刪除操作，既可以使用SQL語句，也可以使用LINQ子語言。

ADO與ADO.Net的共同點，在其內部都是使用SQL語句來對後台資料庫操作。

內在實現上，ADO是基於COM技術，因此變體類型（Variant）無處不在，這是一種通用、萬能類型；而ADO.Net是強類型的，並很好地支持資料庫元數據與XML功能。

## ADO.NET的進化

隨著網路應用程式的進化，ADO.NET也隨之做了許多的改變，但不變的是，ADO.NET的基礎提供了強固的發展支援，這些進化的技術都是植基於ADO.NET的核心元件而來。

長久以來，程式設計師和資料庫總是保持著一種微妙的關係，在商用應用程式中，資料庫一定是不可或缺的元件，這讓程式設計師一定要為了連接與存取資料庫而去學習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利用了抽象化資料結構的方式，將每個資料庫物件都轉換成應用程式物件（entity），而資料欄位都轉換為屬性（property），關聯則轉換為結合屬性（association），讓資料庫的E/R模型完全的轉成物件模型，如此讓程式設計師能用最熟悉的程式語言來呼叫存取。而在抽象化的結構之下，則是高度整合與對應結構的概念層、對應層和儲存層，以及支援Entity Framework的資料提供者（provider），讓資料存取的工作得以順利與完整的進行。

以往在發展像是AJAX應用程式時，伺服端總是需要設計一個HTTP介面埠（end point），通常都會使用Web Service來實作，但是隨著Mashup應用程式的成長，若每次都要為一份（或一組）資料撰寫Web Service或HTTP end point的話，對開發人員也是不小的負擔，而且Web Service只支援XML/SOAP的資料格式，無法相容於Mashup應用程式常用的JSON資料格式，微軟也發現未來的Silverlight應用程式也是會面臨到相同問題。

當時剛好微軟的ADO.NET Entity Framework也正在開發中，它的EDM能力剛好可以提供給WCF資料存取的能力，因此微軟特別以ADO.NET Entity Framework為基礎，開發一個專門提供HTTP端點資料服務的資料供應層，即為WCF Data Services。

## 參見

- ActiveX Data Objects（ADO）
- Open Database Connectivity（ODBC）
- OLE DB

## 基本資料

- 作業系統：Microsoft Windows
- 類型：軟體框架
- 許可協議：MS-EULA、BCL（在微軟參考授權下發布）
- 網站： ADO.NET Overview on MSDN