このセクションでは、where 演算子を使用してデータをフィルタ処理するクエリーを LiveLinq で最適化する方法について、サンプルを使用して説明します。
最初に、次の手順を実行します。
この時点では、プロジェクトは次のようになります。
次に、フォームをダブルクリックし、次のコードを追加します。
C# |
コードのコピー
|
---|---|
// northwind データセットを宣言します NORTHWNDDataSet _ds = new NORTHWNDDataSet(); private void Form1_Load(object sender, EventArgs e) { // データセットにデータをロードします new NORTHWNDDataSetTableAdapters.CustomersTableAdapter() .Fill(_ds.Customers); new NORTHWNDDataSetTableAdapters.OrdersTableAdapter() .Fill(_ds.Orders); } |
データを取得できたので、そのデータを操作します。
ボタンをフォームに追加してダブルクリックし、次のコードを入力します。
C# |
コードのコピー
|
---|---|
private void button1_Click(object sender, EventArgs e) { // ソースデータへの参照を取得します var customers = _ds.Customers; var orders = _ds.Orders; // 最初の顧客の全注文を検索します var q = from o in orders where o.CustomerID == customers[0].CustomerID select o; // クエリーを評価します(1000 回実行) var start = DateTime.Now; int count = 0; for(int i = 0; i < 1000; i++) { foreach (var d in q) count++; } Console.WriteLine("LINQ query done in {0} ms", DateTime.Now.Subtract(start).TotalMilliseconds); } |
ここで、プロジェクトを実行してボタンをクリックすると、Visual Studio の出力ウィンドウに次のように表示されます。
LINK query done in 262 ms
次に、LiveLinq を使用して、このクエリーを最適化します。
最初に、次の using 文をコードの先頭に追加します。
C# |
コードのコピー
|
---|---|
using C1.LiveLinq; using C1.LiveLinq.AdoNet; |
次に、2つ目のボタンをフォームに追加してダブルクリックし、次のコードを入力します。
C# |
コードのコピー
|
---|---|
private void button2_Click(object sender, EventArgs e) { // ソースデータへの参照を取得します var customers = _ds.Customers; var orders = _ds.Orders; // 最初の顧客の全注文を検索します var q = from o in orders.AsIndexed() where o.CustomerID.Indexed() == customers[0].CustomerID select o; // クエリーを評価します(1000 回実行) var start = DateTime.Now; int count = 0; for(int i = 0; i < 1000; i++) { foreach (var d in q) count++; } Console.WriteLine("LiveLinq query done in {0} ms", DateTime.Now.Subtract(start).TotalMilliseconds); } |
コードは、前に使用したプレーンな LINQ バージョンとほぼ同じですが、以下の点だけが異なります。
また、次の点も異なります。
プロジェクトを再度実行し、両方のボタンを何回かクリックすると、次のようなメッセージが表示されます。
LINQ query done in 265 ms
LINQ query done in 305 ms
LINQ query done in 278 ms
LiveLinq query done in 124 ms
LiveLinq query done in 7 ms
LiveLinq query done in 2 ms
プレーンな LINQ クエリーにかかる時間は、常にほぼ同じであることがわかります。一方で、LiveLinq クエリーの速度は、初回からプレーンな LINQ クエリーの約2倍になっています。また、その後の実行では、速度が約 100 倍になっています。この種のクエリーで、この程度のパフォーマンスが得られることは普通です。
LiveLinq クエリーでは、初回実行時にインデックスを構築する必要があるため、その速度は前述のようになります。その後は、同じインデックスが再利用されるため、パフォーマンスが劇的に向上します。インデックスは自動的に管理されます。このため、基底のデータが変更された場合でも、インデックスは常に最新の状態に保たれます。
この例では、Indexed メソッドが最初に実行されたときにインデックスが作成されました。特別な制御が必要な場合は、コードを使用してインデックスを管理することもできます。たとえば、次のコードは、インデックス付きのコレクションを宣言し、CustomerID フィールドに明示的にインデックスを追加します。
C# |
コードのコピー
|
---|---|
var ordersIndexed = _ds.Orders.AsIndexed();
ordersIndexed.Indexes.Add(o => o.CustomerID);
|
インデックスがソースデータに関連付けられており、コレクションがスコープから外れても、インデックスが維持されることに注意してください。上のコードを一旦実行すると、ordersIndexed コレクションがスコープから外れた場合でも、インデックスは有効なままです。
また、AsIndexed メソッドは、変更通知を提供するコレクションでのみサポートされることに注意してください。LiveLinq は、インデックスを維持するために変更を監視する必要があります。WinForms や WPF のデータ連結で一般的に使用されているコレクションでは、すべてこの要件が満たされています。特に、DataTable、DataView、BindingList<T>、ObservableCollection<T>、および LINQ to XML のコレクションでは AsIndexed を使用できます。
LiveLinq インストールに付属する LiveLinqQueries という名前のサンプルには、さまざまなベンチマークの例と、プレーンな CLR オブジェクト、ADO.NET、および XML データに対するクエリーが含まれています。
まとめると、LiveLinq を使用することで、ソート可能な任意のタイプのデータを検索するクエリーを最適化することができます。たとえば、特定の顧客や製品を検索したり、特定の価格帯の製品をリストするクエリーです。これらは標準的なクエリーですが、簡単に最適化して、プレーンな LINQ を使用した場合より 100 倍高速に実行することができます。