Sdílet prostřednictvím


Datová vazba

LINQ to SQL podporuje vazbu na běžné ovládací prvky, jako jsou například ovládací prvky mřížky. LinQ to SQL konkrétně definuje základní vzory pro vazbu k datové mřížce a zpracování vazby hlavních podrobností, a to jak s ohledem na zobrazení, tak aktualizaci.

Základní princip

LINQ to SQL překládá dotazy LINQ na SQL pro spouštění v databázi. Výsledky mají pevně definovaný typIEnumerable. Vzhledem k tomu, že tyto objekty jsou běžné objekty CLR (Common Language Runtime), lze k zobrazení výsledků použít běžnou datová vazbu objektu. Na druhou stranu operace změn (vložení, aktualizace a odstranění) vyžadují další kroky.

Operace

Implicitní vazba na ovládací prvky Windows Forms je dosažena implementací IListSource. Zdroje dat obecné Table<TEntity> (Table<T> v jazyce C# nebo Table(Of T) v jazyce Visual Basic) a obecné DataQuery byly aktualizovány tak, aby implementovaly IListSource. Moduly pro datové vazby uživatelského rozhraní (Windows Forms a Windows Presentation Foundation) testují, zda jejich zdroj dat implementuje IListSource. Proto přiřazení dotazu přímo na zdroj dat prvku ovládání implicitně vyvolává generování kolekcí LINQ to SQL, jako v následujícím příkladu:

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;
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

Totéž se děje se službou Windows Presentation Foundation:

ListView listView1 = new ListView();
var custQuery2 =
    from cust in db.Customers
    select cust;

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

Dim ItemsSource As New ListViewItem
ItemsSource = custQuery2

Generace kolekcí jsou implementovány obecnými Table<TEntity> a obecnými DataQuery v GetList.

Implementace IListSource

LINQ to SQL implementuje IListSource ve dvou umístěních:

  • Zdrojem dat je Table<TEntity>: LINQ to SQL prochází tabulku a vyplní DataBindingList kolekci, která uchovává odkaz na tabulku.

  • Zdroj dat je IQueryable<T>. Existují dva scénáře:

    • Pokud LINQ to SQL najde základní Table<TEntity> z IQueryable<T>, zdroj umožňuje úpravy a situace je stejná jako v prvním bodě.

    • Pokud LINQ to SQL nemůže najít podkladovou Table<TEntity>, zdroj nedovoluje úpravy (například groupby). LINQ to SQL prochází dotaz tak, aby vyplnil obecný SortableBindingList, což je jednoduchá BindingList<T> implementace funkce řazení pro entity T pro danou vlastnost.

Specializované kolekce

Pro mnoho funkcí popsaných dříve v tomto dokumentu BindingList<T> se specializuje na některé různé třídy. Tyto třídy jsou obecné SortableBindingList a obecné DataBindingList. Obě jsou deklarovány jako interní.

Obecný seznam SortableBindingList

Tato třída dědí z BindingList<T> a je tříděnou verzí BindingList<T>. Řazení je řešení v paměti a nikdy nekontaktuje samotnou databázi. BindingList<T> implementuje IBindingList , ale nepodporuje řazení ve výchozím nastavení. BindingList<T> Implementuje se ale s virtuálními IBindingList metodami. Snadno můžete tyto metody přepsat. Obecný SortableBindingList přebírá SupportsSortingCore, SortPropertyCore, SortDirectionCore a ApplySortCore. ApplySortCore je volána podle ApplySort a seřadí seznam položek T pro danou vlastnost.

Výjimka je vyvolána, pokud vlastnost nepatří do T.

Aby bylo možné dosáhnout řazení, LINQ to SQL vytvoří obecnou SortableBindingList.PropertyComparer třídu, která dědí z obecné IComparer.Compare a implementuje výchozí porovnávač pro daný typ T, PropertyDescriptor a směr. Tato třída dynamicky vytváří Comparer typu T, kde T je PropertyTypePropertyDescriptor. Pak se výchozí porovnávač načte ze statického obecného souboru Comparer. Výchozí instance se získá pomocí reflekce.

Obecný SortableBindingList je také základní třídou pro DataBindingList. Generic SortableBindingList nabízí dvě virtuální metody, které umožňují pozastavit nebo obnovit sledování položek při jejich přidávání nebo odstraňování. Tyto dvě metody lze použít pro základní funkce, jako je řazení, ale budou skutečně implementovány vyššími třídami, jako jsou obecné DataBindingList.

Obecný seznam DataBinding

Tato třída dědí z generického SortableBindingLIst. Generic DataBindingList uchovává odkaz na podkladový obecný typ Table obecného typu IQueryable použitého k počátečnímu vyplnění kolekce. Generic DatabindingList přidává sledování změn položek v kolekci, které se provádí přepsáním InsertItem() a RemoveItem(). Implementuje také abstraktní funkci sledování s možností pozastavení a obnovení, čímž se stává sledování podmíněným. Tato funkce umožňuje DataBindingList využívat všechny polymorfní aspekty funkce sledování nadřazených tříd.

Vazba na EntitySets

Vazba na EntitySet je zvláštní případ, protože EntitySet již je kolekce, která implementuje IBindingList. LINQ to SQL přidává podporu řazení a rušení (ICancelAddNew). Třída EntitySet používá k ukládání entit interní seznam. Tento seznam je kolekce nízké úrovně, která je založena na obecném poli, třídě ItemList.

Přidání funkce řazení

Pole poskytují metodu řazení (Array.Sort()), kterou lze použít s kolekcí typu Comparer T. LINQ to SQL používá obecnou třídu SortableBindingList.PropertyComparer popsanou výše v tomto tématu k získání této vlastnosti Comparer a směru, který má být řazen. Přidá se metoda ApplySort ke generickému ItemList pro volání této funkce.

Na straně EntitySet nyní musíte deklarovat podporu pro řazení:

Pokud používáte System.Windows.Forms.BindingSource a připojíte EntitySet<TEntity> k System.Windows.Forms.BindingSource.DataSource, musíte zavolat EntitySet<TEntity>.GetNewBindingList pro aktualizaci BindingSource.List.

Pokud používáte System.Windows.Forms.BindingSource a nastavíte BindingSource.DataMember vlastnost a nastavíte BindingSource.DataSource na třídu, která má vlastnost pojmenovanou v BindingSource.DataMember, která zveřejňuje EntitySet TEntity<, nemusíte volat EntitySet><TEntity>. GetNewBindingList k aktualizaci BindingSource.List, ale ztratíte možnost řazení.

Cacheování

Dotazy LINQ to SQL implementují GetList. Když se třída Windows Forms BindingSource setká s tímto rozhraním, volá GetList() třikrát během jediného připojení. Pokud chcete tuto situaci obejít, LINQ to SQL implementuje mezipaměť pro každou instanci pro uložení a vždy vrátí stejnou vygenerovanou kolekci.

Zrušení

IBindingList definuje metodu AddNew , která se používá ovládacími prvky k vytvoření nové položky z vázané kolekce. Ovládací DataGridView prvek tuto funkci zobrazuje velmi dobře, když poslední viditelný řádek obsahuje hvězdičku v záhlaví. Hvězdička ukazuje, že můžete přidat novou položku.

Kromě této funkce může kolekce také implementovat ICancelAddNew. Tato funkce umožňuje ovládacím prvkům zrušit nebo ověřit, že byla nová upravená položka ověřena nebo ne.

ICancelAddNew bylo implementováno ve všech kolekcích dat LINQ to SQL (generické SortableBindingList a generické EntitySet). V obou implementacích kód provádí takto:

  • Umožňuje vložit a odebrat položky z kolekce.

  • Nesleduje změny, pokud uživatelské rozhraní neuloží úpravu.

  • Nesleduje změny, pokud je edice zrušena (CancelNew).

  • Umožňuje sledování při potvrzení vydání (EndNew).

  • Umožňuje kolekci chovat se normálně, pokud nová položka nepochází z AddNew.

Řešení problémů

Tato část popisuje několik položek, které vám můžou pomoct s řešením potíží s aplikacemi pro datové vazby LINQ to SQL.

  • Je nutné použít vlastnosti; použití pouze polí nestačí. Windows Forms vyžaduje toto použití.

  • Ve výchozím nastavení se image, varbinary a timestamp typy databází mapují na bajtové pole. Nelze tyto objekty zobrazit, protože ToString() není v tomto scénáři podporován.

  • Člen třídy namapovaný na primární klíč má setter, ale LINQ to SQL nepodporuje změnu identity objektu. Proto primární nebo jedinečný klíč, který se používá při mapování, nelze v databázi aktualizovat. Změna v mřížce způsobí výjimku při volání SubmitChanges.

  • Pokud je entita svázaná ve dvou samostatných mřížkách (například předlohová a podrobná mřížka), změna Delete v hlavní mřížce se nepropaguje do mřížky podrobností.

Viz také