Share via


Entity Framework 4.0 Database First と ASP.NET 4 Web Forms を使用したはじめに - パート 2

作成者: Tom Dykstra

Contoso University サンプル Web アプリケーションは、Entity Framework 4.0 と Visual Studio 2010 を使用して ASP.NET Web Forms アプリケーションを作成する方法を示しています。 チュートリアル シリーズの詳細については、シリーズの最初のチュートリアルを参照してください

EntityDataSource コントロール

前のチュートリアルでは、Web サイト、データベース、データ モデルを作成しました。 このチュートリアルでは、Entity Framework データ モデルを EntityDataSource 簡単に操作できるように、ASP.NET が提供するコントロールを操作します。 学生データを GridView 表示および編集するためのコントロール、 DetailsView 新しい学生を追加するためのコントロール、部署 DropDownList を選択するためのコントロール (関連するコースの表示に後で使用します) を作成します。

[インターネット エクスプローラー] ウィンドウのスクリーンショット。学生の名前、登録日、コースの一覧が表示された [学生一覧] ビューが表示されています。

[インターネット エクスプローラー] ウィンドウのスクリーンショット。John Smith の名前と登録日がテキスト フィールドに入力された [新しい学生の追加] ビューが表示されています。

[部門別コース] ビューと部門のドロップダウン メニューが表示されている [インターネット エクスプローラー] ウィンドウのスクリーンショット。

このアプリケーションでは、データベースを更新するページに入力検証を追加しないことに注意してください。また、エラー処理の一部は、運用アプリケーションで必要なほど堅牢ではないことに注意してください。 これで、チュートリアルは Entity Framework に重点を置き、長くなりすぎないようにします。 これらの機能をアプリケーションに追加する方法の詳細については、「ASP.NET Web ページでのユーザー入力の検証」および「ASP.NET ページとアプリケーションでのエラー処理」を参照してください。

EntityDataSource コントロールの追加と構成

まず、エンティティ セットからエンティティを EntityDataSource 読み取 Person るコントロールを People 構成します。

Visual Studio を開き、パート 1 で作成したプロジェクトを操作していることを確認します。 データ モデルを作成してから、または最後に変更してからプロジェクトをビルドしていない場合は、ここでプロジェクトをビルドします。 データ モデルに対する変更は、プロジェクトがビルドされるまでデザイナーで使用できません。

マスター ページ テンプレートを使用して Web フォームを使用して新しい Web ページを 作成し、 Students.aspx という名前を付けます。

Image23

マスター ページとして Site.Master を指定します。 これらのチュートリアル用に作成するすべてのページでは、このマスター ページが使用されます。

Image24

[ソース] ビューでh2、次のContent例に示すように、 という名前Content2のコントロールに見出しを追加します。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
   <h2>Student List</h2>
</asp:Content>

ツールボックスの [データ] タブからコントロールをEntityDataSourceページにドラッグし、見出しの下にドロップし、ID を にStudentsEntityDataSource変更します。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Student List</h2>
    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server">
    </asp:EntityDataSource>
</asp:Content>

デザイン ビューに切り替え、データ ソース コントロールのスマート タグをクリックし、[データ ソースの構成] をクリックして、データ ソースの構成ウィザードを起動します。

Image01

ObjectContext の構成ウィザードの手順で、[名前付き接続] の値として [SchoolEntities] を選択し、DefaultContainerName 値として [SchoolEntities] を選択します。 続けて、 [次へ] をクリックします。

Image02

注: この時点で次のダイアログ ボックスが表示される場合は、先に進む前にプロジェクトをビルドする必要があります。

Image25

[データ選択の構成] ステップで、[EntitySetName] の値として [People] を選択します。 [選択] で、[A ll チェックの選択] ボックスが選択されていることを確認します。 次に、更新と削除を有効にするオプションを選択します。 完了したら、[完了] をクリック します

Image03

削除を許可するデータベース ルールの構成

ユーザーがテーブルから Person 学生を削除できるページを作成します。このページには、他のテーブル (Course、、 StudentGradeおよび OfficeAssignment) とのリレーションシップが 3 つあります。 既定では、他のテーブルのいずれかに関連する行 Person がある場合、データベースは の行を削除できなくなります。 最初に関連する行を手動で削除することも、行を削除するときに自動的に削除するようにデータベースを Person 構成することもできます。 このチュートリアルの学生レコードの場合は、関連データを自動的に削除するようにデータベースを構成します。 学生はテーブル内でのみ関連する行を StudentGrade 持つことができるため、3 つのリレーションシップのうち 1 つだけを構成する必要があります。

このチュートリアルに従ってプロジェクトからダウンロードした School.mdf ファイルを使用している場合は、これらの構成の変更が既に行われているため、このセクションをスキップできます。 スクリプトを実行してデータベースを作成した場合は、次の手順を実行してデータベースを構成します。

[サーバー エクスプローラー] で、パート 1 で作成したデータベース ダイアグラムを開きます。 と の間のリレーションシップ (テーブル間Personの線) を右クリックし、[プロパティ] を選択します。StudentGrade

Image04

[ プロパティ ] ウィンドウで、 INSERT と UPDATE の仕様 を展開し、 DeleteRule プロパティを Cascade に設定します。

Image05

ダイアグラムを保存して閉じます。 データベースを更新するかどうかを確認するメッセージが表示されたら、[ はい] をクリックします。

モデルがメモリ内のエンティティをデータベースの実行内容と同期するようにするには、データ モデルで対応するルールを設定する必要があります。 SchoolModel.edmx を開き、 と StudentGradeの間Personの関連付け線を右クリックし、 [プロパティ] を選択します。

Image21

[ プロパティ ] ウィンドウで、 End1 OnDeleteCascade に設定します。

Image22

SchoolModel.edmx ファイルを保存して閉じ、プロジェクトをリビルドします。

一般に、データベースが変更されると、モデルを同期する方法についていくつかの選択肢があります。

  • 特定の種類の変更 (テーブル、ビュー、ストアド プロシージャの追加や更新など) の場合は、デザイナーを右クリックし、[ データベースからモデルを更新 ] を選択して、デザイナーが自動的に変更を行います。
  • データ モデルを再生成します。
  • このような手動更新を行います。

この場合は、モデルを再生成したり、リレーションシップの変更の影響を受けるテーブルを更新したりできますが、フィールド名をもう一度変更する必要があります (から FirstName )。FirstMidName

GridView コントロールを使用したエンティティの読み取りと更新

このセクションでは、コントロールを使用して学生を GridView 表示、更新、または削除します。

Students.aspx を開くか、切り替えてデザイン ビューに切り替えます。 ツールボックスの [データ] タブで、コントロールをGridViewコントロールのEntityDataSource右側にドラッグし、名前を付けてStudentsGridViewスマート タグをクリックし、データ ソースとして [StudentsEntityDataSource] を選択します。

Image06

[ スキーマの更新 ] をクリックし (確認を求められた場合は [はい ] をクリックします)、[ ページングの有効化]、[ 並べ替えの有効化]、[ 編集の有効化]、[ 削除の有効化] の順にクリックします。

[ 列の編集] をクリックします

Image10

[ 選択したフィールド ] ボックス で、PersonIDLastNameHireDate を削除します。 通常、ユーザーにはレコード キーを表示せず、採用日は学生には関係なく、名前の両方の部分を 1 つのフィールドに配置するため、必要なのは名前フィールドのいずれか 1 つだけです)。

Image11

[FirstMidName] フィールドを選択し、[このフィールドを TemplateField に変換] をクリックします。

EnrollmentDate に対して同じ操作を行います。

Image13

[ OK] を クリックし、[ ソース ビュー] に切り替えます。 残りの変更は、マークアップで直接行う方が簡単です。 コントロール マークアップは GridView 次の例のようになります。

<asp:GridView ID="StudentsGridView" runat="server" AllowPaging="True" 
        AllowSorting="True" AutoGenerateColumns="False" DataKeyNames="PersonID" 
        DataSourceID="StudentsEntityDataSource">
        <Columns>
            <asp:CommandField ShowDeleteButton="True" ShowEditButton="True" />
            <asp:TemplateField HeaderText="FirstMidName" SortExpression="FirstMidName">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="EnrollmentDate" SortExpression="EnrollmentDate">
                <EditItemTemplate>
                    <asp:TextBox ID="TextBox2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="Label2" runat="server" Text='<%# Bind("EnrollmentDate") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

コマンド フィールドの後の最初の列は、現在名を表示しているテンプレート フィールドです。 このテンプレート フィールドのマークアップを次の例のように変更します。

<asp:TemplateField HeaderText="Name" SortExpression="LastName">
                <EditItemTemplate>
                    <asp:TextBox ID="LastNameTextBox" runat="server" Text='<%# Bind("LastName") %>'></asp:TextBox>
                    <asp:TextBox ID="FirstNameTextBox" runat="server" Text='<%# Bind("FirstMidName") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="LastNameLabel" runat="server" Text='<%# Eval("LastName") %>'></asp:Label>,
                    <asp:Label ID="FirstNameLabel" runat="server" Text='<%# Eval("FirstMidName") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

表示モードでは、2 つの Label コントロールに姓と名が表示されます。 編集モードでは、姓と名を変更できるように、2 つのテキスト ボックスが用意されています。 表示モードのLabelコントロールと同様に、 および Eval 式は、データベースに直接接続 ASP.NET データ ソース コントロールとまったく同じように使用Bindします。 唯一の違いは、データベース列ではなくエンティティ プロパティを指定することです。

最後の列は、登録日を表示するテンプレート フィールドです。 このフィールドのマークアップを次の例のように変更します。

<asp:TemplateField HeaderText="Enrollment Date" SortExpression="EnrollmentDate">
                <EditItemTemplate>
                    <asp:TextBox ID="EnrollmentDateTextBox" runat="server" Text='<%# Bind("EnrollmentDate", "{0:d}") %>'></asp:TextBox>
                </EditItemTemplate>
                <ItemTemplate>
                    <asp:Label ID="EnrollmentDateLabel" runat="server" Text='<%# Eval("EnrollmentDate", "{0:d}") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

表示モードと編集モードの両方で、書式指定文字列 "{0,d}" によって日付が "短い日付" 形式で表示されます。 (お使いのコンピューターは、このチュートリアルで示されている画面イメージとは異なる方法でこの形式を表示するように構成されている場合があります)。

これらの各テンプレート フィールドでは、デザイナーで既定で式が使用 Bind されていますが、要素内の式に Eval 変更されていることに ItemTemplate 注意してください。 式は Bind 、コード内のデータに GridView アクセスする必要がある場合に備えて、コントロール プロパティでデータを使用できるようにします。 このページでは、コード内のこのデータにアクセスする必要がないため、 を使用 Evalすると効率的です。 詳細については、「 データ コントロールからデータを取得する」を参照してください。

パフォーマンスを向上させるために EntityDataSource コントロール マークアップを変更する

コントロールのマークアップEntityDataSourceで、 属性と DefaultContainerName 属性をConnectionString削除し、 属性にContextTypeName="ContosoUniversity.DAL.SchoolEntities"置き換えます。 これは、オブジェクト コンテキスト クラスでハードコーディングされたものとは異なる接続を使用する必要がない限り、コントロールを作成 EntityDataSource するたびに行う必要がある変更です。 属性を ContextTypeName 使用すると、次の利点があります。

  • パフォーマンスが向上します。 コントロールはEntityDataSource、 属性と DefaultContainerName 属性を使用してデータ モデルをConnectionString初期化すると、すべての要求にメタデータを読み込むための追加作業を実行します。 属性を指定 ContextTypeName する場合、これは必要ありません。
  • Entity Framework 4.0 で生成されたオブジェクト コンテキスト クラス (このチュートリアルなど SchoolEntities ) では、遅延読み込みは既定でオンになっています。 つまり、ナビゲーション プロパティは、必要なときに自動的に関連データと共に読み込まれます。 遅延読み込みについては、このチュートリアルの後半で詳しく説明します。
  • オブジェクト コンテキスト クラス (この場合は クラス) に適用したカスタマイズは、コントロールを SchoolEntities 使用 EntityDataSource するコントロールで使用できます。 オブジェクト コンテキスト クラスのカスタマイズは、このチュートリアル シリーズでは取り上げられない高度なトピックです。 詳細については、「 Entity Framework で生成された型の拡張」を参照してください。

マークアップは次の例のようになります (プロパティの順序が異なる場合があります)。

<asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EntitySetName="People"
        EnableDelete="True" EnableUpdate="True">
    </asp:EntityDataSource>

属性は EnableFlattening 、外部キー列がエンティティ プロパティとして公開されていないため、以前のバージョンの Entity Framework で必要だった機能を参照します。 現在のバージョンでは 、外部キーの関連付けを使用できます。つまり、多対多の関連付けを含むすべての外部キー プロパティが公開されます。 エンティティに外部キー プロパティがあり、 複合型がない場合は、この属性を に設定したままにすることができます False。 既定値 Trueは であるため、マークアップから 属性を削除しないでください。 詳細については、「 オブジェクトのフラット化 (EntityDataSource)」を参照してください。

ページを実行すると、学生と従業員の一覧が表示されます (次のチュートリアルでは、学生のみをフィルター処理します)。 名と姓が一緒に表示されます。

Image07

表示を並べ替えるには、列名をクリックします。

任意の行の [編集] を クリックします。 テキスト ボックスが表示され、姓と名を変更できます。

Image08

[ 削除] ボタンも機能します。 登録日を含み、行が消える行の [削除] をクリックします。 (登録日のない行は講師を表し、参照整合性エラーが発生する可能性があります。次のチュートリアルでは、この一覧をフィルター処理して、学生のみを含めます)。

ナビゲーション プロパティからのデータの表示

ここで、各学生が登録されているコースの数を知りたいとします。 Entity Framework は、エンティティの StudentGrades ナビゲーション プロパティにその情報を Person 提供します。 データベース設計では、学生が成績を割り当てずにコースに登録することはできないため、このチュートリアルでは、コースに関連付けられているテーブル行に行 StudentGrade を含めるのは、コースに登録されているのと同じであると仮定できます。 Courses(ナビゲーション プロパティは講師専用です)。

コントロールの EntityDataSource 属性をContextTypeName使用すると、そのプロパティにアクセスすると、Entity Framework によってナビゲーション プロパティの情報が自動的に取得されます。 これは 遅延読み込みと呼ばれます。 ただし、追加の情報が必要になるたびにデータベースを個別に呼び出すので、これは非効率的な場合があります。 コントロールによって返されるすべてのエンティティに対してナビゲーション プロパティからデータが EntityDataSource 必要な場合は、データベースへの 1 回の呼び出しでエンティティ自体と共に関連データを取得する方が効率的です。 これは一括読み込みと呼ばれ、ナビゲーション プロパティの一括読み込みを指定するには、 コントロールの プロパティをIncludeEntityDataSource設定します。

Students.aspx では、すべての学生のコース数を表示する必要があるため、一括読み込みが最適な選択肢です。 すべての学生を表示し、そのうちの一部のコースの数のみを表示する場合 (マークアップに加えてコードを記述する必要があります)、遅延読み込みが適している可能性があります。

Students.aspx を開くか、Students.aspx に切り替えてデザイン ビューに切り替え、[StudentsEntityDataSourceプロパティ] ウィンドウで [Include]\(含める\) プロパティを StudentGrades に設定します。 (複数のナビゲーション プロパティを取得する場合は、名前をコンマで区切って指定できます ( StudentGrades、Courses など)。

Image19

[ソース] ビューに切り替えます。 コントロールの最後asp:TemplateFieldStudentsGridView要素の後に、次の新しいテンプレート フィールドを追加します。

<asp:TemplateField HeaderText="Number of Courses">
                <ItemTemplate>
                    <asp:Label ID="Label1" runat="server" Text='<%# Eval("StudentGrades.Count") %>'></asp:Label>
                </ItemTemplate>
            </asp:TemplateField>

式では Eval 、ナビゲーション プロパティ StudentGradesを参照できます。 このプロパティには Count コレクションが含まれているため、学生が登録されているコースの数を表示するために使用できるプロパティがあります。 後のチュートリアルでは、コレクションではなく単一のエンティティを含むナビゲーション プロパティのデータを表示する方法について説明します。 (ナビゲーション プロパティのデータを表示するために要素を使用 BoundField できないことに注意してください)。

ページを実行すると、各学生が登録されているコースの数が表示されます。

[インターネット エクスプローラー] ウィンドウのスクリーンショット。John Smith の名前と登録日がテキスト フィールドに入力された [新しい学生の追加] ビューが表示されています。

DetailsView コントロールを使用したエンティティの挿入

次の手順では、新しい学生を追加できるコントロールを持つ DetailsView ページを作成します。 ブラウザーを閉じ、 Site.Master マスター ページを使用して新しい Web ページを作成します。 ページに StudentsAdd.aspx という名前を付け、 ソース ビューに切り替えます。

次のマークアップを追加して、 という名前Content2のコントロールの既存のマークアップをContent置き換えます。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Add New Students</h2>
    <asp:EntityDataSource ID="StudentsEntityDataSource" runat="server"
        ContextTypeName="ContosoUniversity.DAL.SchoolEntities" EnableFlattening="False"
        EnableInsert="True" EntitySetName="People">
    </asp:EntityDataSource>
    <asp:DetailsView ID="StudentsDetailsView" runat="server" 
        DataSourceID="StudentsEntityDataSource" AutoGenerateRows="False"
        DefaultMode="Insert">
        <Fields>
            <asp:BoundField DataField="FirstMidName" HeaderText="First Name" 
                SortExpression="FirstMidName" />
            <asp:BoundField DataField="LastName" HeaderText="Last Name" 
                SortExpression="LastName" />
            <asp:BoundField DataField="EnrollmentDate" HeaderText="Enrollment Date" 
                SortExpression="EnrollmentDate" />
             <asp:CommandField ShowInsertButton="True" />
       </Fields>
    </asp:DetailsView>
</asp:Content>

このマークアップは、挿入を EntityDataSource 有効にする点を除き、 Students.aspx で作成したコントロールと似たコントロールを作成します。 コントロールと同様に GridView 、コントロールの DetailsView バインドされたフィールドは、エンティティ プロパティを参照する点を除き、データベースに直接接続するデータ コントロールの場合とまったく同じようにコーディングされます。 この場合、コントロールは行の DetailsView 挿入にのみ使用されるため、既定のモードを に Insert設定しました。

ページを実行し、新しい学生を追加します。

[インターネット エクスプローラー] ウィンドウのスクリーンショット。John Smith の名前と登録日がテキスト フィールドに入力された [新しい学生の追加] ビューが表示されています。

新しい学生を挿入しても何も起こりませんが、 Students.aspx を実行すると、新しい学生情報が表示されます。

Drop-Down リストにデータを表示する

次の手順では、コントロールを DropDownList 使用して EntityDataSource エンティティ セットにコントロールをデータバインドします。 チュートリアルのこの部分では、この一覧では多くのことを行いません。 ただし、その後の部分では、リストを使用して、ユーザーが部門を選択して、部門に関連付けられているコースを表示できるようにします。

Courses.aspx という名前の新しい Web ページを作成します。 [ソース] ビューで、 という名前Content2のコントロールにContent見出しを追加します。

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2>Courses by Department</h2>
</asp:Content>

デザイン ビューで、前と同じようにページにコントロールを追加EntityDataSourceします。ただし、今回は という名前を付けますDepartmentsEntityDataSource[EntitySetName] の値として [Departments]\(部門\) を選択し、[DepartmentID] プロパティと [Name]\(名前\) プロパティのみを選択します。

Image15

ツールボックスの [標準] タブからコントロールをDropDownListページにドラッグし、名前を付けてDepartmentsDropDownListスマート タグをクリックし、[データ ソースの選択] を選択してデータソース構成ウィザードを開始します。

Image16

[ データ ソースの選択 ] ステップで、データ ソースとして [DepartmentsEntityDataSource ] を選択し、[ スキーマの更新] をクリックし、表示するデータ フィールドとして [名前 ] を選択し、値データ フィールドとして DepartmentID を選択します。 [OK] をクリックします。

Image17

Entity Framework を使用してコントロールをデータバインドするために使用するメソッドは、エンティティとエンティティ プロパティを指定する場合を除き、他の ASP.NET データ ソース コントロールと同じです。

[ソース] ビューに切り替え、コントロールの直前に "部門の選択: " をDropDownList追加します。

Select a department:
    <asp:DropDownList ID="DropDownList1" runat="server" 
        DataSourceID="EntityDataSource1" DataTextField="Name" 
        DataValueField="DepartmentID">
    </asp:DropDownList>

アラームとして、 属性と DefaultContainerName 属性を 属性にEntityDataSource置き換えてConnectionString、この時点でコントロールのマークアップをContextTypeName="ContosoUniversity.DAL.SchoolEntities"変更します。 多くの場合、データ ソース コントロールにリンクされているデータ バインド コントロールを作成してからコントロール マークアップを変更 EntityDataSource することをお勧めします。これは、変更を加えた後、デザイナーがデータ バインド コントロールの [スキーマの更新] オプションを提供しないためです。

ページを実行すると、ドロップダウン リストから部署を選択できます。

[Internet エクスプローラー browser]\(インターネット エクスプローラー ブラウザー\) ウィンドウのスクリーンショット。[部門別コース] ビューと部門のドロップダウン メニューが表示されています。

これで、 コントロールの使用の概要が完了します EntityDataSource 。 通常、このコントロールの操作は、テーブルと列ではなくエンティティとプロパティを参照する点を除き、他の ASP.NET データ ソース コントロールを操作する場合と変わりはありません。 唯一の例外は、ナビゲーション プロパティにアクセスする場合です。 次のチュートリアルでは、データをフィルター処理、グループ化、および順序付けするときに、コントロールで EntityDataSource 使用する構文が他のデータ ソース コントロールと異なる場合もあることがわかります。