共用方式為


資料繫結 (LINQ to SQL)

更新: November 2007

LINQ to SQL 支援與通用控制項 (如方格控制項) 的繫結。特別的是,LINQ to SQL 定義了繫結至資料方格以及處理主從式繫結的基本模式,而且都可以進行顯示和更新作業。

基礎準則

LINQ to SQL 會將 LINQ 查詢轉譯為 SQL,以便在資料庫上執行。而產生的結果會是強型別 (Strongly Typed) IEnumerable。因為這些物件是一般 Common Language Runtime (CLR) 物件,所以一般物件資料繫結 (Data Binding) 可以用來顯示結果。另一方面,變更作業 (插入、更新和刪除) 則需要額外的步驟。

作業

實作 IListSource,就可以隱含地繫結至 Windows Forms 控制項。C# 中的資料來源泛型 Table<TEntity> (C# 中的 Table<T> 或 Visual Basic 中的 Table(Of T)) 和泛型 DataQuery 已更新為實作 IListSource。使用者介面 (UI) 資料繫結引擎 (Windows Form 和 Windows Presentation Foundation) 兩者都會測試其資料來源是否實作 IListSource。因此,直接對控制項資料來源撰寫查詢,會隱含地呼叫 LINQ to SQL 集合產生,如下列範例所示:

Dim dataGrid1 As New DataGrid()
Dim dataGrid2 As New DataGrid()
Dim dataGrid3 As New DataGrid()

Dim custQuery = _
    From cust In db.Customers _
    Select cust

dataGrid1.DataSource = custQuery
dataGrid2.DataSource = custQuery
dataGrid2.DataMember = "Orders"

Dim bs = _
    New BindingSource()
bs.DataSource = custQuery
dataGrid3.DataSource = bs
DataGrid dataGrid1 = new DataGrid();
DataGrid dataGrid2 = new DataGrid();
DataGrid dataGrid3 = new DataGrid();

var custQuery =
    from cust in db.Customers
    select cust;
dataGrid1.DataSource = custQuery;
dataGrid2.DataSource = custQuery;
dataGrid2.DataMember = "Orders";

BindingSource bs = new BindingSource();
bs.DataSource = custQuery;
dataGrid3.DataSource = bs;

而 Windows Presentation Foundation 也會發生相同的狀況:

Dim listView1 As New ListView()
Dim custQuery2 = _
From cust In db.Customers _
Select cust

Dim ItemsSource As New ListViewItem
ItemsSource = custQuery2
ListView listView1 = new ListView();
var custQuery2 =
    from cust in db.Customers
    select cust;

ListViewItem ItemsSource = new ListViewItem();
ItemsSource = (ListViewItem)custQuery2;

集合產生是透過 GetList 中的泛型 Table<TEntity> 和泛型 DataQuery 予以實作。

IListSource 實作

LINQ to SQL 會在兩個位置實作 IListSource

  • 資料來源是 Table<TEntity>:LINQ to SQL 會瀏覽資料表以填入 DataBindingList 集合,這個集合會保存對該資料表的參考。

  • 資料來源是 IQueryable<T>。有兩種案例:

    • 如果 LINQ to SQL 可以從 IQueryable<T> 找到基礎 Table<TEntity>,則來源會允許進行編輯,而且狀況與第一點相同。

    • 如果 LINQ to SQL 找不到基礎 Table<TEntity>,則來源不允許進行編輯 (例如,groupby)。LINQ to SQL 會瀏覽查詢以填入泛型 SortableBindingList,這是簡單的 BindingList<T>,用來實作所指定屬性之 T 實體 (Entity) 的排序功能。

特殊化集合

BindingList<T> 已針對本文件之前描述的許多功能,特殊化為一些不同類別。這些類別是泛型 SortableBindingList 和泛型 DataBindingList。這兩種類別都是宣告為內部。

泛型 SortableBindingList

這個類別繼承自 BindingList<T>,而且是 BindingList<T> 的可排序版本。排序動作僅在記憶體中執行,並不會連絡資料庫本身。BindingList<T> 會實作 IBindingList,但是預設不支援排序。不過,BindingList<T> 會使用虛擬 core 方法來實作 IBindingList。您可以輕鬆地覆寫這些方法。泛型 SortableBindingList 會覆寫 SupportsSortingCoreSortPropertyCoreSortDirectionCoreApplySortCoreApplySortCore 是透過 ApplySort 進行呼叫,而且會排序所指定屬性的 T 項目清單。

如果屬性不屬於 T,則會引發例外狀況 (Exception)。

為了進行排序,LINQ to SQL 會建立繼承自泛型 IComparer.Compare 的泛型 SortableBindingList.PropertyComparer 類別,並實作所指定型別 T 的預設比較子 (Comparer)、PropertyDescriptor 以及方向。這個類別會動態建立 T 的 Comparer,其中 T 是 PropertyDescriptorPropertyType。然後,會從靜態泛型 Comparer 中擷取預設比較子。而預設執行個體是使用反映 (Reflection) 取得。

泛型 SortableBindingList 也是 DataBindingList 的基底類別。泛型 SortableBindingList 提供兩種虛擬方法,以暫止或繼續項目的新增/移除追蹤 (Tracking)。這兩種方法都適用於排序這類的基本功能,但是會由泛型 DataBindingList 這類的上層類別實際實作。

泛型 DataBindingList

這個類別繼承自泛型 SortableBindingLIst。泛型 DataBindingList 會保存對泛型 IQueryable 之基礎泛型 Table (用於初始填入集合) 的參考。泛型 DatabindingList 會覆寫 InsertItem() 和 RemoveItem(),以將項目新增/移除的追蹤加入至集合。也會實作抽象的暫止/繼續追蹤功能,讓追蹤具有條件性。這個功能可以讓泛型 DataBindingList 利用父類別之追蹤功能的所有多型使用。

繫結至 EntitySet

因為 EntitySet 已經是實作 IBindingList 的集合,所以繫結至 EntitySet 是特殊情況。LINQ to SQL 會加入排序和取消 (ICancelAddNew) 支援。EntitySet 類別會使用內部清單來儲存實體。這份清單是以泛型陣列 (泛型 ItemList 類別) 為基礎的低階集合。

加入排序功能

陣列提供的排序方法 (Array.Sort()) 可以與 T 的 Comparer 搭配使用。而 LINQ to SQL 會使用本主題之前所述的泛型 SortableBindingList.PropertyComparer 類別,來取得屬性的這個 Comparer 以及排序方向。ApplySort 方法會加入至泛型 ItemList,以呼叫這個功能。

您現在必須在 EntitySet 端上宣告排序支援:

快取

LINQ to SQL 查詢實作 GetList。Windows Forms BindingSource 類別符合這個介面時,會針對單一連接呼叫三次 GetList()。為了解決這個情況,LINQ to SQL 會針對每個執行個體實作快取,以儲存且一律傳回相同的產生集合。

取消

IBindingList 定義 AddNew 方法,讓控制項用來從繫結集合建立新項目。DataGridView 控制項會在最後一個可見資料列的標頭顯示星號,能充分地呈現這個功能特徵。星號表示您可以加入新的項目。

除了這個功能之外,集合也可以實作 ICancelAddNew。這個功能允許控制項取消或驗證是否已驗證過新的編輯過項目。

ICancelAddNew 是在所有 LINQ to SQL 資料繫結集合中實作 (泛型 SortableBindingList 和泛型 EntitySet)。在這兩個實作中,程式碼執行如下:

  • 允許項目插入後又從集合中移除。

  • 只要 UI 未認可編輯,就不追蹤變更。

  • 只要取消編輯,就不追蹤變更 (CancelNew)。

  • 允許在認可編輯時進行追蹤 (EndNew)。

  • 如果新項目不是來自 AddNew,則讓集合正常運作。

疑難排解

本節會呼叫數個項目,協助您疑難排解 LINQ to SQL 資料繫結應用程式。

  • 您必須使用屬性,只使用欄位是不夠的。Windows Forms 需要這種使用方式。

  • image、varbinary 和 timestamp 資料庫類型預設會對應至位元組陣列。因為此案例不支援 ToString(),所以無法顯示這些物件。

  • 對應至主索引鍵的類別成員會有 setter,但是 LINQ to SQL 不支援物件識別變更。因此,無法更新資料庫中用於對應的主/唯一索引鍵。在您呼叫 SubmitChanges 時,方格中的變更會導致例外狀況。

  • 如果實體是繫結在兩個不同方格中 (例如,一個是主版方格,而另一個詳細方格),則主版方格中的 Delete 不會散佈至詳細方格。

請參閱

其他資源

背景資訊 (LINQ to SQL)