DataSource for Entity Framework for WinForms
ライブビュー
設計時の機能 > ライブビュー

ライブビューは強力な機能です。したがって、少し時間をかけてさらにライブビューの機能についても見ていきます。ライブビューは、より強力なデータ連結を目的にして設計されています。実際、アプリケーション全体を(LiveLinq フォーム内の)LINQ とデータ連結だけで開発できると言ってもいいくらい強力です。

DataSource for Entity Framework のライブビュー機能を LiveLinq と呼びます。これは、クライアント側のインメモリ機能として、Entity Framework や RIA サービスのデータのみならず、XML(LINQ to XML オブジェクトモデル)、ADO.NET DataSet など、メモリ内の任意の監視可能なコレクションに適用できます。

たとえば、Entity Framework データと何か他のデータ(Web サービスから取得した XML など)に対してライブビューを使用して、それらのデータを統合し、統合されたデータに完全な機能を備えたデータ連結を簡単に提供できます。これは、さまざまなソースからデータを取得するアプリケーションを構築するための強力なツールです。ここでは、LiveLinq を Entity Framework で使用する方法を中心に説明します。詳細については、「C1LiveLinq」を参照してください。

実際には、「ビューのカスタマイズ」で、このようなカスタマイズの例について既に確認しました。しかし、そこでは、ビューのプロパティ(フィールド)を変更し、1つの LINQ 演算子 Select を適用しただけです。ここでは、さらに追加の LINQ 演算子を適用して、ビューを変更してみます。ここで行うことは、「ビューのカスタマイズ」の内容に似ていますが、C1DataSource を使用する代わりにすべてをコードで行います。

ライブビューを使用するには、次の手順に従います。

  1. コードでのデータソースの操作」の例で作成したプロジェクトを使用して、新しいフォームを追加し、フォームにデータグリッド dataGridView1 を追加します。
  2. フォームクラスに次のコードを追加します。ここでは、「コードでのデータソースの操作」で推奨されているパターンに従います。
    コードのコピー
    Private _scope As EntityClientScope = Program.ClientCache.CreateScope()
    
    コードのコピー
    private EntityClientScope _scope = Program.ClientCache.CreateScope();
    
  3. スコープから Products データを取得したら、ライブビューを作成し、フォームのコンストラクタでそのビューにグリッドを連結します。
    コードのコピー
    _viewProducts =
         (From p In _scope.GetItems(Of Product)()
          Where Not p.Discontinued And p.UnitPrice >= 30
          Order By p.UnitPrice
          Select New With
          {
              p.ProductID,
              p.ProductName,
              p.CategoryID,
              p.Category.CategoryName,
              p.SupplierID,
              .Supplier = p.Supplier.CompanyName,
              p.UnitPrice,
              p.QuantityPerUnit,
              p.UnitsInStock,
              p.UnitsOnOrder
          }).AsDynamic()
     dataGridView1.DataSource = _viewProducts
    
    コードのコピー
    _viewProducts =
    (from p in _scope.GetItems<Product>()
                            where !p.Discontinued && p.UnitPrice >= 30
                            orderby p.UnitPrice
                            select new
                            {
                                ProductID = p.ProductID,
                                ProductName = p.ProductName,
                                CategoryID = p.CategoryID,
                                CategoryName = p.Category.CategoryName,
                                SupplierID = p.SupplierID,
                                Supplier = p.Supplier.CompanyName,
                                UnitPrice = p.UnitPrice,
                                QuantityPerUnit = p.QuantityPerUnit,
                                UnitsInStock = p.UnitsInStock,
                                UnitsOnOrder = p.UnitsOnOrder
                            }).AsDynamic();
    dataGridView1.DataSource = _viewProducts;
    

    この例では、いくつかの LiveLinq 演算子(WhereOrderBySelect)を適用しました。販売終了しておらず、単価が 30 以上の製品を含むビューを定義し、ビューを単価別にソートしました。

    ここでは、ビューをプライベートフィールド _viewProducts に保存することにしました。

    コードのコピー
    Private _viewProducts As View(Of Object)
    
    コードのコピー
    private View<dynamic> _viewProducts;
    

    これは、後で必要になるというだけの理由です。必要にならないなら、ビューのローカル変数を使用してもかまいません。

    構文的には、_viewProducts に対して記述したクエリーは単なる標準の LINQ です。これは、C1DataSource なしで、標準の LINQ to Objects を使用して行うこともできます。コードは同じですが、_scope.GetItems<Product>() の代わりに ObjectContext.Products などを使用します。実際、このプロジェクトを実行したら、標準の LINQ の結果と LiveLinq の結果を比較するために、この後すぐにこれを実行してみます。

  4. ここで、プロジェクトを実行します。グリッドには、フィルタ処理された一連の製品、つまり販売終了していない "高価" な製品が指定された列に指定された順序で表示されます。すべての列が変更可能であり、グリッドで行を追加および削除できることにも注目してください。さらに、列ヘッダーをクリックすることで、実行時にグリッドをソートすることもできます。

この完全なデータ連結サポートを正しく評価するために、C1DataSource を使用せず、代わりに標準の LINQ to Objects を使用した場合の結果と比べてみます。比較は簡単です。コード内の _scope.GetItems<Product>()Program.ObjectContext.Products に置き換えるだけです。また、ライブビューではなくなるため、タイプ C1.LiveLinq.LiveViews.View を削除し、代わりに 'var' キーワードを使用してコンパイルします。違いは明らかです。標準の LINQ では、グリッド内のデータは読み取り専用となり、グリッドはソートをサポートしません。

しかし、ライブビューは、これよりはるかに強力な機能を提供します。標準の LINQ to Objects では、LINQ ステートメントでカスタム Select を使用しないという厳しい条件の下であっても、一部の単純なプロパティの変更を除き、ソースデータの変更を反映できないスナップショットが生成されます。一方、ライブビューは、ソースデータの変更を自動的に反映する動的な "ライブ" ビューを提供します。このため、ほとんどの場合、コードでアプリケーションのさまざまな部分の変更を同期する必要はなく、ビューの "ライブ" 変更の自動化をデータ連結に任せることができるため、アプリケーション開発がシンプルになります。

これらのビューが本当に "ライブ" であることを確認するために、2つのフォームを横に並べて開いてみます。アプリケーションを実行し、「ビューのカスタマイズ」で作成した Custom Columns フォームと、ここで作成した Client Side Querying フォームを開きます。CustomColumns フォームで製品に変更を加え、もう一方のフォームにどのように反映されるかを確認します。たとえば、ある製品の UnitCost30 より大きくすると、それが自動的に2つめのフォームに表示されます。

別の例として、ライブビューが自動的に基底のデータと同期することを確認するために、次の手順に従います。

  1. ユーザーコントロールクラスのライブビューメンバを追加します。
    コードのコピー
    Private _seafoodProductsView As ClientView(Of Product)
    
    コードのコピー
    private ClientView<Product> _seafoodProductsView;
    
  2. 次のコードをフォームのコンストラクタに追加します。
    コードのコピー
    _seafoodProductsView = _scope.GetItems(Of Product)().AsFiltered(Function(p) p.CategoryID.Value = 8)
    
    コードのコピー
    _seafoodProductsView = _scope.GetItems<Product>().AsFiltered(p => p.CategoryID == 8);
    
  3. フォームに btnRaisebtnCut という名前の2つのボタンを追加し、フォームのコードに次のハンドラを追加します。
    コードのコピー
    Private Sub raiseButton_Click(sender As System.Object, e As System.EventArgs)
      For Each p In _seafoodProductsView
      p.UnitPrice *= 1.2
       Next
      End Sub
         Private Sub cutButton_Click(sender As System.Object, e As System.EventArgs)
           For Each p In _seafoodProductsView
      p.UnitPrice /= 1.2
        Next
      End Sub
    
    コードのコピー
    private void raiseButton_Click(object sender, EventArgs e)
    {
        foreach (var p in _seafoodProductsView)
            p.UnitPrice *= 1.2m;
    }
    private void cutButton_Click(object sender, EventArgs e)
    {
        foreach (var p in _seafoodProductsView)
            p.UnitPrice /= 1.2m;
    }
    
  4. アプリケーションを保存、ビルド、および実行します。これらのボタンを押して、シーフード製品の単価が 30 以上になるとグリッドに表示され、単価が 30 を下回ると非表示になることを確認します。これはすべて自動的に行われます。グリッドをリフレッシュしたり同期するためのコードを特に記述する必要はありませんでした。
  5. ほぼすべての GUI 関連コードの記述がライブビューによって容易に(かつミスが少なく)なることを確認するために、現在の行数を示すラベルを追加してみます。C1DataSource がない場合は、通常、メソッド内で行をカウントし、行数が変更される可能性があるコード内のすべての場所でそのメソッドを呼び出す必要があります。この例では、そのような場所は3つあります。初期ロード時と、raiseButton_Click ボタンと cutButton_Click ボタンが押されたときに呼び出される2つのメソッド内です。したがって、実際のアプリケーションは言うまでもなく、この単純な例でさえも、データの変化と表示を同期することはそれほど簡単ではありません。ライブビューは、この同期のためのコードをすべて不要にします。フィルタ処理、ソート、プロジェクション(Where、OrderBy、Select)を含むビューでこれがどのように機能するかは既に見てきました。これは、Count などの集計操作を含むビューでも機能します。ここで多少異なる点は、通常の LINQ Count は1つの数値を返し、それにはコントロールを連結できないということです。そこで C1DataSource は、単一の数値でなくライブビューを返す特別な演算子 LiveCount を提供しており、これを使用してデータ連結を行うことができます。この連結は、1行のコードで作成できます。
    C#
    コードのコピー
    labelCount.DataBindings.Add(new Binding("Text",
                    _viewProducts.LiveCount(), "Value"));