定義クエリ - EF Designer

このチュートリアルでは、EF Designer を使用して、定義クエリおよび対応するエンティティ型をモデルに追加する方法について説明します。 定義クエリは、データベース ビューで提供されるものと同様の機能を提供するためによく使用されますが、データベースではなく、モデルでビューが定義されます。 定義クエリを使用すると、.edmx ファイルの DefiningQuery 要素で指定されている SQL ステートメントを実行できます。 詳細については、「SSDL 仕様」の DefiningQuery を参照してください。

定義クエリを使用するときは、モデルでエンティティ型も定義する必要があります。 エンティティ型は、定義クエリによって公開されるデータを表示するために使用されます。 このエンティティ型を使用して表示されるデータは読み取り専用であることに注意してください。

パラメーター化されたクエリを定義クエリとして実行することはできません。 ただし、データを表示するエンティティ型の挿入、更新、および削除関数をストアド プロシージャにマッピングすると、データを更新できます。 詳細については、ストアド プロシージャを使用した挿入、更新、削除に関する記事を参照してください。

このトピックでは、次のタスクを実行する方法について説明します。

  • 定義クエリを追加する
  • モデルにエンティティ型を追加する
  • 定義クエリをエンティティ型にマップする

前提条件

このチュートリアルを完了するための要件を次に示します。

プロジェクトをセットアップする

このチュートリアルでは、Visual Studio 2012 以降を使用します。

  • Visual Studio を開きます。
  • [ファイル] メニューの [新規作成] をポイントし、 [プロジェクト] をクリックします。
  • 左ペインで [Visual C#] をクリックし、[コンソール アプリケーション] テンプレートを選択します。
  • プロジェクトの名前として「DefiningQuerySample」と入力し、[OK] をクリックします。

 

School データベースに基づいてモデルを作成する

  • ソリューション エクスプローラーでプロジェクト名を右クリックし、[追加] をポイントして、[新しい項目] をクリックします。

  • 左側のメニューから [データ] を選択し、[テンプレート] ペインの [ADO.NET Entity Data Model] を選択します。

  • ファイル名として「DefiningQueryModel.edmx」と入力し、[追加] をクリックします。

  • [モデルのコンテンツの選択] ダイアログ ボックスで、[データベースから生成] を選択し、[次へ] をクリックします。

  • [新しい接続] をクリックします。 [接続のプロパティ] ダイアログ ボックスで、サーバー名 (例: (localdb)\mssqllocaldb) を入力し、認証方法を選択します。データベース名として「School」と入力し、[OK] をクリックします。 指定したデータベース接続設定に従って、[データ接続の選択] ダイアログ ボックスが更新されます。

  • [データベース オブジェクトの選択] ダイアログ ボックスで、[テーブル] ノードをオンにします。 これにより、すべてのテーブルが School モデルに追加されます。

  • [完了] をクリックします。

  • ソリューション エクスプローラーで、DefiningQueryModel.edmx ファイルを右クリックし、[プログラムから開く] を選択します。

  • [XML (テキスト) エディター] を選択します。

    XML Editor

  • 次のメッセージが表示されたら、[はい] をクリックします。

    Warning 2

 

定義クエリを追加する

この手順では、XML エディターを使用して、.edmx ファイルの SSDL セクションに、定義クエリとエンティティ型を追加します。 

  • .edmx ファイルの SSDL セクションに、EntitySet 要素を追加します (5 から 13 行目)。 次の情報を指定します。
    • EntitySet 要素の Name 属性と EntityType 属性だけを指定します。
    • EntityType 属性では、エンティティ型の完全修飾名が使用されます。
    • 実行する SQL ステートメントを DefiningQuery 要素で指定します。
    <!-- SSDL content -->
    <edmx:StorageModels>
      <Schema Namespace="SchoolModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/11/edm/ssdl">
        <EntityContainer Name="SchoolModelStoreContainer">
           <EntitySet Name="GradeReport" EntityType="SchoolModel.Store.GradeReport">
              <DefiningQuery>
                SELECT CourseID, Grade, FirstName, LastName
                FROM StudentGrade
                JOIN
                (SELECT * FROM Person WHERE EnrollmentDate IS NOT NULL) AS p
                ON StudentID = p.PersonID
              </DefiningQuery>
          </EntitySet>
          <EntitySet Name="Course" EntityType="SchoolModel.Store.Course" store:Type="Tables" Schema="dbo" />
  • 次に示すように、.edmx ファイルの SSDL セクションに、EntityType 要素を 追加します。 以下に注意してください:
    • 上記の EntitySet 要素の Name 属性の値は、EntityType 属性の値に対応します。ただし、EntityType 属性では、エンティティ型の完全修飾名が使用されます。
    • プロパティ名は、上記の DefiningQuery 要素の SQL ステートメントから返される列名に対応します。
    • この例では、キー値が一意になるように、エンティティ キーは 3 つのプロパティで構成されています。
    <EntityType Name="GradeReport">
      <Key>
        <PropertyRef Name="CourseID" />
        <PropertyRef Name="FirstName" />
        <PropertyRef Name="LastName" />
      </Key>
      <Property Name="CourseID"
                Type="int"
                Nullable="false" />
      <Property Name="Grade"
                Type="decimal"
                Precision="3"
                Scale="2" />
      <Property Name="FirstName"
                Type="nvarchar"
                Nullable="false"
                MaxLength="50" />
      <Property Name="LastName"
                Type="nvarchar"
                Nullable="false"
                MaxLength="50" />
    </EntityType>

Note

後でモデルの更新ウィザード ダイアログを実行すると、定義クエリなど、ストレージ モデルに加えた変更が上書きされます。

 

モデルにエンティティ型を追加する

この手順では、EF Designer を使用して、概念モデルにエンティティ型を追加します。  以下に注意します。

  • 上記の EntitySet 要素のエンティティの Name は、EntityType 属性の値に対応します。
  • プロパティ名は、上記の DefiningQuery 要素の SQL ステートメントから返される列名に対応します。
  • この例では、キー値が一意になるように、エンティティ キーは 3 つのプロパティで構成されています。

EF Designer でモデルを開きます。

  • DefiningQueryModel.edmx をダブルクリックします。

  • 次のメッセージが表示が表示されたら、[はい] をクリックします。

    Warning 2

 

モデルを編集するためのデザイン サーフェイスを提供する Entity Designer が表示されます。

  • デザイナー画面を右クリックし、[新規追加] ->[エンティティ] の順に選択します。
  • エンティティ名に GradeReport を指定し、[キー プロパティ]CourseID を指定します。
  • GradeReport エンティティを右クリックし、[新規追加] ->[スカラー プロパティ] の順に選択します。
  • プロパティの既定の名前を FirstName に変更します。
  • 別のスカラー プロパティを追加し、名前に LastName を指定します。
  • 別のスカラー プロパティを追加し、名前に Grade を指定します。
  • [プロパティ] ウィンドウで、GradeType プロパティを Decimal に変更します。
  • FirstName および LastName プロパティを選択します。
  • [プロパティ] ウィンドウで、EntityKey プロパティの値を True に変更します。

結果として、.edmx ファイルの CSDL セクションに次の要素が追加されました。

    <EntitySet Name="GradeReport" EntityType="SchoolModel.GradeReport" />

    <EntityType Name="GradeReport">
    . . .
    </EntityType>

 

定義クエリをエンティティ型にマップする

この手順では、[マッピングの詳細] ウィンドウを使用して、概念エンティティ型とストレージ エンティティ型をマップします。

  • デザイン サーフェイスで GradeReport エンティティを右クリックし、[テーブル マッピング] を選択します。
    [マッピングの詳細] ウィンドウが表示されます。
  • ([テーブル] の下にある) [<テーブルまたはビューの追加>] ドロップダウン リストから [GradeReport] を選択します。
    概念エンティティ型と GradeReport ストレージ エンティティ型の間の既定のマッピングが表示されます。
    Mapping Details3

結果として、.edmx ファイルのマッピング セクションに、EntitySetMapping 要素が追加されます。 

    <EntitySetMapping Name="GradeReports">
      <EntityTypeMapping TypeName="IsTypeOf(SchoolModel.GradeReport)">
        <MappingFragment StoreEntitySet="GradeReport">
          <ScalarProperty Name="LastName" ColumnName="LastName" />
          <ScalarProperty Name="FirstName" ColumnName="FirstName" />
          <ScalarProperty Name="Grade" ColumnName="Grade" />
          <ScalarProperty Name="CourseID" ColumnName="CourseID" />
        </MappingFragment>
      </EntityTypeMapping>
    </EntitySetMapping>
  • アプリケーションをコンパイルします。

 

コード内で定義クエリを呼び出す

GradeReport エンティティ型を使用して、定義クエリを実行できるようになりました。 

    using (var context = new SchoolEntities())
    {
        var report = context.GradeReports.FirstOrDefault();
        Console.WriteLine("{0} {1} got {2}",
            report.FirstName, report.LastName, report.Grade);
    }