モデル バインドと Web Forms を使用したデータの取得と表示
このチュートリアル シリーズでは、ASP.NET Web Forms プロジェクトでモデル バインドを使用する基本的な側面について説明します。 モデル バインドを使用すると、データ ソース オブジェクト (ObjectDataSource や SqlDataSource など) を扱うよりも、データの操作が簡単になります。 このシリーズは入門資料から始まり、後のチュートリアルでより高度な概念に進んでいきます。
モデル バインド パターンは、あらゆるデータ アクセス テクノロジで動作します。 このチュートリアルでは Entity Framework を使用しますが、最も身近なデータ アクセス テクノロジを使用することもできます。 GridView、ListView、DetailsView、FormView コントロールなどのデータ バインド サーバー コントロールから、データの選択、更新、削除、および作成に使用するメソッドの名前を指定します。 このチュートリアルでは、SelectMethod の値を指定します。
そのメソッド内で、データを取得するためのロジックを指定します。 次のチュートリアルでは、UpdateMethod、DeleteMethod、InsertMethod の値を設定します。
C# または Visual Basic で完全なプロジェクトをダウンロードできます。 ダウンロード可能なコードは、Visual Studio 2012 以降で動作します。 このチュートリアルで示す Visual Studio 2017 テンプレートとは若干異なる Visual Studio 2012 テンプレートを使用します。
このチュートリアルでは、アプリケーションを Visual Studio で実行します。 また、ホスティング プロバイダーにアプリケーションをデプロイし、インターネット経由で利用できるようにすることもできます。 Microsoft は、最大 10 個の Web サイトに無料の Web ホスティングを提供しています。
無料の Azure 試用版アカウント。 Visual Studio Web プロジェクトを Azure App Service Web Apps にデプロイする方法については、Visual Studio を使った ASP.NET の Web 配置シリーズを参照してください。 このチュートリアルでは、Entity Framework Code First Migrations を使用して SQL Server データベースを Azure SQL Database に展開する方法についても示しています。チュートリアルで使用するソフトウェアのバージョン
- Microsoft Visual Studio 2017 または Microsoft Visual Studio Community 2017
このチュートリアルは Visual Studio 2012 と Visual Studio 2013 でも機能しますが、ユーザー インターフェイスとプロジェクト テンプレートにはいくつかの違いがあります。
作成する内容
このチュートリアルでは、次のことについて説明します。
- コースに登録されている学生が所属する大学を反映するデータ オブジェクトを作成する
- オブジェクトからデータベース テーブルをビルドする
- データベースにテスト データを設定する
- Web Forms にデータを表示する
プロジェクトを作成する
Visual Studio 2017 で、ContosoUniversityModelBinding という ASP.NET Web アプリケーション (.NET Framework) プロジェクトを作成します。
[OK] を選択します。 テンプレートを選択するためのダイアログ ボックスが表示されます。
Web Forms テンプレートを選択します。
必要に応じて、認証を [個々のユーザー アカウント] に変更します。
[OK] を選択すると、プロジェクトが作成されます。
サイトの外観を変更する
サイトの外観をカスタマイズするには、いくつかの変更を加えます。
Site.Master ファイルを開きます。
[My ASP.NET アプリケーション] ではなく [Contoso University] と表示されるようにタイトルを変更します。
<title><%: Page.Title %> - Contoso University</title>
ヘッダー テキストを [アプリケーション名] から [Contoso University] に変更します。
<div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a class="navbar-brand" runat="server" href="~/">Contoso University</a> </div>
ナビゲーション ヘッダー リンクをサイトに適したリンクに変更します。
[バージョン情報] と [連絡先] のリンクを削除し、代わりに [学生] ページへのリンクを作成します。
<ul class="nav navbar-nav"> <li><a runat="server" href="~/">Home</a></li> <li><a runat="server" href="~/Students">Students</a></li> </ul>
Site.Master を保存します。
学生データを表示する Web フォームを追加する
ソリューション エクスプローラーで、サーバー プロジェクトを右クリックし、[追加]、[新しい項目] を選択します。
[新しい項目の追加] ダイアログ ボックスで、[マスター ページを含む Web フォーム] テンプレートを選択し、「Students.aspx」という名前を付けます。
[追加] を選択します。
Web フォームのマスター ページで、Site.Master を選択します。
[OK] を選択します。
データ モデルを追加する
Models フォルダーに、「UniversityModels.cs」という名前のクラスを追加します。
Models を右クリックし、[追加]、[新しい項目] の順に選択します。 [新しい項目の追加] ダイアログ ボックスが表示されます。
左側のナビゲーション メニューから、[コード]、[クラス] の順に選択します。
クラスに UniversityModels.cs という名前を付け、[追加] を選択します。
このファイルでは、次のように
SchoolContext
、Student
、Enrollment
、Course
クラスを定義します。using System; using System.Collections.Generic; using System.Data.Entity; using System.ComponentModel.DataAnnotations; namespace ContosoUniversityModelBinding.Models { public class SchoolContext : DbContext { public DbSet<Student> Students { get; set; } public DbSet<Enrollment> Enrollments { get; set; } public DbSet<Course> Courses { get; set; } } public class Student { [Key, Display(Name = "ID")] [ScaffoldColumn(false)] public int StudentID { get; set; } [Required, StringLength(40), Display(Name="Last Name")] public string LastName { get; set; } [Required, StringLength(20), Display(Name = "First Name")] public string FirstName { get; set; } [EnumDataType(typeof(AcademicYear)), Display(Name = "Academic Year")] public AcademicYear Year { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } } public class Enrollment { [Key] public int EnrollmentID { get; set; } public int CourseID { get; set; } public int StudentID { get; set; } public decimal? Grade { get; set; } public virtual Course Course { get; set; } public virtual Student Student { get; set; } } public class Course { [Key] public int CourseID { get; set; } public string Title { get; set; } public int Credits { get; set; } public virtual ICollection<Enrollment> Enrollments { get; set; } } public enum AcademicYear { Freshman, Sophomore, Junior, Senior } }
SchoolContext
クラスは、データベース接続とデータの変更を管理するDbContext
から派生します。Student
クラスで、FirstName
、LastName
、Year
プロパティに適用される属性に注目してください。 このチュートリアルでは、データ検証のためにこれらの属性を使用します。 コードを簡略化するために、これらのプロパティのみがデータ検証属性でマークされます。 実際のプロジェクトでは、検証を必要とするすべてのプロパティに検証属性を適用します。UniversityModels.cs を保存します。
クラスに基づいてデータベースを設定する
このチュートリアルでは、Code First Migrations を使用してオブジェクトとデータベース テーブルを作成します。 これらのテーブルには、学生とそのコースに関する情報が格納されます。
[ツール]>[NuGet パッケージ マネージャー]>[パッケージ マネージャー コンソール] の順に選択します。
パッケージ マネージャー コンソールで、次のコマンドを実行します。
enable-migrations -ContextTypeName ContosoUniversityModelBinding.Models.SchoolContext
コマンドが正常に完了すると、移行が有効になっていることを示すメッセージが表示されます。
Configuration.cs という名前のファイルが作成されていることに注意してください。
Configuration
クラスには、データベース テーブルにテスト データを事前に設定できるSeed
メソッドがあります。
データベースを事前に設定する
Configuration.cs を開きます。
Seed
メソッドに次のコードを追加します。 また、ContosoUniversityModelBinding. Models
名前空間に対してusing
ステートメントを追加します。namespace ContosoUniversityModelBinding.Migrations { using System; using System.Data.Entity; using System.Data.Entity.Migrations; using System.Linq; using ContosoUniversityModelBinding.Models; internal sealed class Configuration : DbMigrationsConfiguration<SchoolContext> { public Configuration() { AutomaticMigrationsEnabled = false; } protected override void Seed(SchoolContext context) { context.Students.AddOrUpdate( new Student { FirstName = "Carson", LastName = "Alexander", Year = AcademicYear.Freshman }, new Student { FirstName = "Meredith", LastName = "Alonso", Year = AcademicYear.Freshman }, new Student { FirstName = "Arturo", LastName = "Anand", Year = AcademicYear.Sophomore }, new Student { FirstName = "Gytis", LastName = "Barzdukas", Year = AcademicYear.Sophomore }, new Student { FirstName = "Yan", LastName = "Li", Year = AcademicYear.Junior }, new Student { FirstName = "Peggy", LastName = "Justice", Year = AcademicYear.Junior }, new Student { FirstName = "Laura", LastName = "Norman", Year = AcademicYear.Senior }, new Student { FirstName = "Nino", LastName = "Olivetto", Year = AcademicYear.Senior } ); context.SaveChanges(); context.Courses.AddOrUpdate( new Course { Title = "Chemistry", Credits = 3 }, new Course { Title = "Microeconomics", Credits = 3 }, new Course { Title = "Macroeconomics", Credits = 3 }, new Course { Title = "Calculus", Credits = 4 }, new Course { Title = "Trigonometry", Credits = 4 }, new Course { Title = "Composition", Credits = 3 }, new Course { Title = "Literature", Credits = 4 } ); context.SaveChanges(); context.Enrollments.AddOrUpdate( new Enrollment { StudentID = 1, CourseID = 1, Grade = 1 }, new Enrollment { StudentID = 1, CourseID = 2, Grade = 3 }, new Enrollment { StudentID = 1, CourseID = 3, Grade = 1 }, new Enrollment { StudentID = 2, CourseID = 4, Grade = 2 }, new Enrollment { StudentID = 2, CourseID = 5, Grade = 4 }, new Enrollment { StudentID = 2, CourseID = 6, Grade = 4 }, new Enrollment { StudentID = 3, CourseID = 1 }, new Enrollment { StudentID = 4, CourseID = 1 }, new Enrollment { StudentID = 4, CourseID = 2, Grade = 4 }, new Enrollment { StudentID = 5, CourseID = 3, Grade = 3 }, new Enrollment { StudentID = 6, CourseID = 4 }, new Enrollment { StudentID = 7, CourseID = 5, Grade = 2 } ); context.SaveChanges(); } } }
Configuration.cs を保存します。
パッケージ マネージャー コンソールで、コマンド add-migration initial を実行します。
コマンド update-database を実行します。
このコマンドの実行時に例外が発生した場合、
Seed
メソッドの値とStudentID
およびCourseID
値が異なる場合があります。 これらのデータベース テーブルを開き、StudentID
およびCourseID
用の既存の値を検索します。 これらの値をコードに追加して、Enrollments
テーブルをシード処理します。
GridView コントロールを追加する
データベース データを入力すると、そのデータを取得して表示する準備が整いました。
Students.aspx を開きます。
MainContent
プレースホルダーを探します。 そのプレースホルダー内に、このコードを含む GridView コントロールを追加します。<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server"> <asp:GridView runat="server" ID="studentsGrid" ItemType="ContosoUniversityModelBinding.Models.Student" DataKeyNames="StudentID" SelectMethod="studentsGrid_GetData" AutoGenerateColumns="false"> <Columns> <asp:DynamicField DataField="StudentID" /> <asp:DynamicField DataField="LastName" /> <asp:DynamicField DataField="FirstName" /> <asp:DynamicField DataField="Year" /> <asp:TemplateField HeaderText="Total Credits"> <ItemTemplate> <asp:Label Text="<%# Item.Enrollments.Sum(en => en.Course.Credits) %>" runat="server" /> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> </asp:Content>
考慮事項:
GridView 要素の
SelectMethod
プロパティに設定されている値に注目してください。 この値は、次の手順で作成する GridView データの取得に使用するメソッドを指定します。ItemType
プロパティは、先ほど作成したStudent
クラスに設定されます。 この設定を使用すると、マークアップでクラス プロパティを参照できます。 たとえば、Student
クラスにはEnrollments
という名前のコレクションがあります。Item.Enrollments
を使用してそのコレクションを取得し、LINQ 構文を使用して各学生の登録済み合計単位数を取得できます。
Students.aspx を保存します。
コードを追加してデータを取得する
Students.aspx 分離コード ファイルで、SelectMethod
値に指定されたメソッドを追加します。
Students.aspx.cs を開きます。
ContosoUniversityModelBinding. Models
およびSystem.Data.Entity
名前空間にusing
ステートメントを追加します。using ContosoUniversityModelBinding.Models; using System.Data.Entity;
SelectMethod
に指定したメソッドを追加します。public IQueryable<Student> studentsGrid_GetData() { SchoolContext db = new SchoolContext(); var query = db.Students.Include(s => s.Enrollments.Select(e => e.Course)); return query; }
Include
句はクエリのパフォーマンスを向上させますが、必須ではありません。Include
句がない場合、遅延読み込みを使用してデータを取得します。これは、関連するデータを取得するたびにデータベースに個別のクエリを送信する必要があります。Include
句を使用すると、一括読み込みを使用してデータを取得します。つまり、1 つのデータベース クエリですべての関連データを取得します。 関連データを使用しない場合、より多くのデータを取得するため、一括読み込みの効率は低下します。 ただし、この場合、一括読み込みでは関連データがレコードごとに表示されるため、最適なパフォーマンスが得られます。関連データを読み込む場合のパフォーマンスに関する考慮事項の詳細については、ASP.NET MVC アプリケーションでの Entity Framework での関連データの読み取りに関する記事の「関連データの遅延読み込み、一括読み込み、明示的読み込み」セクションを参照してください。
既定では、データはキーとしてマークされたプロパティの値で並べ替えられます。 別の並べ替え値を指定するために、
OrderBy
句を追加できます。 この例では、既定のStudentID
プロパティが並べ替えに使用されます。 データの並べ替え、ページング、フィルター処理に関する記事では、ユーザーは並べ替える列を選択できます。Students.aspx.cs を保存します。
アプリケーションを実行する
Web アプリケーション (F5) を実行し、[学生] ページに移動すると、次の内容が表示されます。
モデル バインド メソッドの自動生成
このチュートリアル シリーズで作業する場合は、チュートリアルからプロジェクトにコードをコピーするだけでできます。 ただし、この方法の欠点の 1 つは、Visual Studio によって提供されるモデル バインド メソッドのコードを自動生成する機能に気付かない可能性があることです。 独自のプロジェクトで作業する場合、コードの自動生成によって時間を節約し、操作を実装する方法の感覚をつかむのに役立ちます。 このセクションでは、自動コード生成機能について説明します。 このセクションは単なる情報提供であり、プロジェクトで実装する必要があるコードは含まれていません。
マークアップ コードで SelectMethod
、UpdateMethod
、InsertMethod
、DeleteMethod
プロパティ用の値を設定する場合は、[新しいメソッドを作成] オプションを選択できます。
Visual Studio は、適切なシグネチャを使用して分離コード内にメソッドを作成するだけでなく、操作を実行する実装コードも生成します。 自動コード生成機能を使用する前に ItemType
プロパティを最初に設定した場合、生成されたコードではその型が操作に使用されます。 たとえば、UpdateMethod
プロパティを設定すると、次のコードが自動的に生成されます。
// The id parameter name should match the DataKeyNames value set on the control
public void studentsGrid_UpdateItem(int id)
{
ContosoUniversityModelBinding.Models.Student item = null;
// Load the item here, e.g. item = MyDataLayer.Find(id);
if (item == null)
{
// The item wasn't found
ModelState.AddModelError("", String.Format("Item with id {0} was not found", id));
return;
}
TryUpdateModel(item);
if (ModelState.IsValid)
{
// Save changes here, e.g. MyDataLayer.SaveChanges();
}
}
ここでも、このコードをプロジェクトに追加する必要はありません。 次のチュートリアルでは、新しいデータを更新、削除、および追加するためのメソッドを実装します。
まとめ
このチュートリアルでは、データ モデル クラスを作成し、それらのクラスからデータベースを生成しました。 データベース テーブルにテスト データを入力しました。 モデル バインドを使用してデータベースからデータを取得し、GridView にデータを表示しました。
このシリーズの次のチュートリアルでは、データの更新、削除、および作成を有効にします。