皆様、こんにちは!

今回から何回か、下記のようなビジネス 向け Windows ストアアプリ開発に関するテーマを、コードを交えて、不定期に Blog を書いていきたいと思っています。連続して執筆できる場合もあれば、そうでない場合(他トピックが割り込む場合)もあるかと思いますが、ぜひお付き合いくださいませ。

テーマ一覧:

1.データ

      データバインディング

      データコントロール(GridViewのロード、セマンティックズーム等)

      OData、バックグラウンドでのダウンロード

      サービスへのアクセス(WCF、JSON等)、Live SDK

2.ローカリゼーション

3.定期的なタイル更新とプッシュ通知 ※Mobile Services を除く予定??

4.非同期

5ローカルデータとローミングデータ

6.WinRT の再利用可能なコンポーネント

7.バックグラウンドタスクとロックスクリーンアプリ

8.その他

9.MVVM 編へと続く…

今回は、ストアプリケーションで使用されるデータベースのモデルを実装する方法(の一つ)を示します。

回作成しようとしているビジネス Windows ストアアプリ

CookBookApp と呼ばれる、例によってレシピ情報を提供する 1 つのアプリケーションに、全ての機能を統合していきます。Windows ストアアプリとして、デザイン要件を満たす必要があるほか、データとデータ ソースへの接続が必要です。マイクロソフトの最新の ORM フレームワークである、Entity Framework 5 を使用してデータ モデルを開発する方法が提示します。

DB モデルを実装した後、Windows ストア アプリケーションからデータを扱ういくつかの方法が必要となります。Windows ストアアプリケーションからデータベースに直接接続する方法は、基本的にはありません。Windows ストアアプリでリモートデータを扱うには、何らかの Entity Framework モデルを介して、ある種の Web サービス (RESTまたは SOAP) を実装することによってのみ可能です。.NET 4.5WCF 4.5 の最新バージョンを使用して WCF サービスを実装する方法を、提示します。WCF よりライトなサービスインフラストラクチャを開発する場合には、ASP.NET Web API REST サービスを実装します。

バックエンドが作成できたら、Entity Framework モデルを介して、REST または SOAP サービスを通じて、リモートデータを使用してクライアント側(ストアアプリ)の開発が可能になります。最初にデータを提示するための UI を開発します。Visual Studio 2012 に準備されているWindows ストアアプリ用のテンプレートを使い、HttpClient 等を使います。また、検索コントラクトを実装し、このアプリに Windows 8 の検索機能を統合します。

※ また .NET を使用せず WinRT のみを使用してデータ ソースを実装する事も可能です。このためには、 SQLite ライブラリを使用します。SQLite は、自己完結型、サーバーレス、ゼロ構成、トランザクションの SQL データベース エンジンを実装するソフトウェアライブラリあり、世界で最も広く導入されている SQL データベース エンジンです。WinRT のネイティブ サポートにより、このライブラリを使用して、WinRT で実行できます。

必要な環境

このチュートリアルを開始するには、Visual Studio 2012 と、少なくとも SQL Server 2012 Express Edition または Windows Azure 上の SQL Database が必要となります。

データベースのモデル

今回のアプリのデータベースのモデルは非常に簡単です。3 つのテーブルがあります: 場所、料理、そして街。これらのテーブルの関係は下の図にある通りです。レシピの画像は、Contoso Cookbook のものを使う予定です。

image

SQL データベースは、この記事の最後に作成されます。まずは机上でデータベース モデルの実装を開始できます。データベースモデルを実装するために、Entity Framework 5 および Code First の技術を使用します。Visual Studio 2012 を起動し、新しいプロジェクト-> Windows -> クラスライブラリを選択します。 

image

空のクラスライブラリプロジェクトを作成したら、エンティティの実装に入ります。上記の図に示した通りに従い、3つの .NET クラス群を作ります : Dish、Town、Place、です。

そのために必要な手順は下記の通りです :

  • プロジェクトを右クリック
  • 新しいクラスを追加
  • 名前を変更: Dish

同様の手順を、Town クラスと Place クラスにつき行います。

Dish

using System.Collections.Generic;
using System.Runtime.Serialization;
 
namespace DataModel
{
    public partial class Dish
    {
        public int? DishID { get; set; }
 
        public string Name { get; set; }
 
        public string Message { get; set; }
 
        public string Description { get; set; }
 
        public string Image { get; set; }
 
        //リレーションシップ 1対多
        //多くの Places に一つの Dish あり
       
        public ICollection<Place> Places { get; set; }
    }
}

Town

using System.Collections.Generic;
using System.Runtime.Serialization;
 
namespace DataModel
{
 
    public partial class Town
    {
        public int? TownID { get; set; }
 
        public string Name { get; set; }
 
        public string Description { get; set; }
 
        public string Image { get; set; }
 
        //リレーションシップ 1対多
        //多くの places は一つの Town に存在し得る
        public ICollection<Place> Places { get; set; }
    }
}

Place

using System.Collections.Generic;
using System.Runtime.Serialization;
 
namespace DataModel
{
    public partial class Place
    {
 
        public int? PlaceID { get; set; }
 
        public string Name { get; set; }
 
        public string Description { get; set; }
 
        public int? DishID { get; set; }
 
        public string Message { get; set; }
       
        public string Type { get; set; }
 
        public int? TownID { get; set; }
 
        public string Image { get; set; }
 
 
        //Dish への 1 リレーション 
        public Dish PlaceDish { get; set; }
 
        //Town への 1 リレーション
        public Town PlaceTown { get; set; } 
    }
}

 

Code First を使うので、2つのエンティティのリレーションシップを確立する必要があります。だからこそ、Place クラスの最後の2つのプロパティを設定した訳です。また、前の2つのクラスのIColletion プロパティも同様です。これで、Code First によって SQL Server 上にリレーションシップを確立することが可能です。規定値では、PlaceID は Place テーブルのプライマリキーであり、DishId と TownID もそれぞれのクラスのプライマリキーとなります。

DB コンテキストの作成

これでエンティティができましたので、DBContext を作成します。これにより、データベースに対する全ての操作と、トランザクション処理が管理できます。DBContext を実装する前に、Entity Framework への参照を追加する必要があります。現在、Entity Framework は .NET から分離されていますので、NuGet を使ってこれを行います。

1. 参照設定を右クリックして、NuGet パッケージの管理をクリックします。

  image 

検索ボックスで、Entity Framework とタイプして、エンターキーを押します。当該パッケージがリストに追加されます。インストールボタンをクリックしてインストールしてください。下の図は、NuGet パッケージの管理ダイアログボックスです。License Agreement に同意して、ダイアログボックスを閉じます。

image

 

CookBookApp.cs の DataContext class の実装

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace DataModel
{
    public class CookBookApp: DbContext
    {
        public CookBookApp() : base("cookbook_db") 
        {
            Configuration.LazyLoadingEnabled = false;
        }
 
        //Entity セット
        public DbSet<Place> Places { get; set; }
        public DbSet<Dish>  Dishes  { get; set; }
        public DbSet<Town>  Towns  { get; set; }
 
 
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            //1対多リレーションシップの確立(Town と Place)
            modelBuilder.Entity<Place>()
                .HasRequired(x => x.PlaceTown)
                .WithMany(d => d.Places)
                .WillCascadeOnDelete(true);
 
            //1対多リレーションシップの確立(Dish と Place)
            modelBuilder.Entity<Place>()
                .HasRequired(x => x.PlaceDish)
                .WithMany(d=>d.Places)
                .WillCascadeOnDelete(true);
 
            base.OnModelCreating(modelBuilder);
        }
    }
}

ここにあるように、ModelCreation バーチャルメソッドをオーバーライドして、エンティティ間のリレーションシップを確立しています。これは古典的な1対多リレーションです。 

実装の最後に、SQL Server への接続文字列を追加する必要があります。接続文字列は、DBContext の実装で決定したものと、同じ名前である必要があります。

2. 新しいアイテムの追加: App.config ファイルを開き、下記の設定(ConnectionString)を追加します。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 
  <connectionStrings>
    <add name="cexplorer_db" 
         providerName="System.Data.SqlClient" 
         connectionString="Data Source=.\sqlexpress;Initial Catalog=cookbook_db;Integrated Security=True"/>
  </connectionStrings>
</configuration>

SQL インスタンス名に基づいて、ConnectionString は適宜変更してください。この時点ではデータベースは SQL Server 上には存在していません。もし当該 SQL Server 上に同じ名前のデータベースがある場合、Entity Framwork はその既存のデータベースに、テーブルを追加します。

最後に、テストをして確認をしておきましょう。コンソールアプリケーションを作成し、正しいモデルが実装されたかを確認します。

1. ファイル->追加->新しいプロジェクトを、順にクリックします。

2. コンソールアプリケーションを選択し、名前を適当に(例:EFModelTest)つけてOKをクリックします。

image

 

3.先ほどの EFModel プロジェクト同様、Entity Framework NuGet から取得して追加し、EFModel プロジェクトを参照します。

4.Program.cs ファイルを開いて、下記の通り実装します:

using DataModel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace EFModelText
{
    class Program
    {
        static void Main(string[] args)
        {
 
            CookBookApp ctx = new CookBookApp();
 
            var dish = new Dish() { DishID = 1, Description = "Description", Name = "DishName", Message = "Message", Image = "test.jpg" };
            var town= new Town(){TownID=1, Name= "TownName", Description="Description", Image=""};
            ctx.Dishes.Add(dish);
            ctx.Towns.Add(town);
            ctx.SaveChanges();
            var place = new Place() { PlaceID = 1, Name = "Place Name", Description = "Description", Image = "Test.jpg", Message = "Message title", DishID = 1, TownID = 1 };
            ctx.Places.Add(place);
            ctx.SaveChanges();
 
            var plc = ctx.Places.FirstOrDefault();
            Console.WriteLine("データベースから Place を取得");
            Console.WriteLine("Place を取得したデータベース:{0}", plc.Name);
            Console.Read();
           
        }
    }
}

このまま、開始 ボタンを押して実行します。コンソールアプリケーションが立ち上がり、エンティティが無事にデータベースに作成されたことがわかります。 

image

すなわち、cookbook_dbSQL Server 上に作られ、エンティティは、テストプログラムから作成されているということになります。

image

Code First アプローチは、このようにきわめて強力です。ConnectionString は修正する必要がありますが、それ以外は Model First アプローチによりコードで書いた通りに稼働します。

※ 接続先を SQL Azure Database にしておけば、Azure 上にデータベースが作成されます。

次回はこれを、ASP.NET Web API を使って、REST API を使用して呼び出す方法の一つを、実装します。直近の予定のテーマとしては、Part 2REST サービスの実装、Part 3完成品アプリの解説に続けていきます。

鈴木 章太郎