データ ポイント

EF6、EF7、および ASP.NET 5 の混乱状態

Julie Lerman

Julie Lerman2015 年 1 月のデータ ポイントのコラム「Entity Framework 7 に備える」(英語) では、コラム執筆時点での EF7 アルファ版の状態を確認することで、EF7 の新機能を特集しました。ちょうどそのコラムの公開が迫っていた 2014 年 12 月、EF チームは EF7 のリリース準備に関して重要な決断を下しました。そのため、コラムの公開直前に、次の 2 文をあわてて追記することになりました。「ブログに投稿された『EF7—Priorities, Focus and Initial Release』(EF7 の優先順位、重点項目、および初回リリース、bit.ly/1ykagF0、英語) によると、EF7 の初回リリースでは、ASP.NET 5 との互換性に重点が置かれます。その後のリリースで、多くの機能が追加される予定です」

コラムの公開後、この文章の意味を正確に理解するのは難しく、少々混乱を招くのではないかと考えました。読者の皆さんには、EF7 の初回リリースは何をターゲットにしているか、このリリースを使用すべきかどうか、どのような選択肢があるかを理解してほしいと考えています。

そうすれば、次期バージョンの Microsoft .NET Framework と、ASP.NET 5 アプリの実行基盤となる .NET Framework との違いを理解できるようになります。今回はこのような点を大まかに見ていきますが、2015 年 3 月号の Daniel Roth のコラム「ASP.NET 5 ランタイムの詳細」を参考にして理解を深めてください。さらに、EF6 と EF7 が混在する状態に適合させる方法についても取り上げます。

ASP.NET 5 (別名 ASP.NET vNext) は、完全版の .NET Framework への依存度、さらには Windows 自体への依存度を減らすように設計されています。ASP.NET 5 の下、ASP.NET MVC 6 やクラス ライブラリ、さらにはコンソール アプリケーションでも、新しい統合機能のセットを使用して、Web アプリケーションや Web API を作成することができます。ASP.NET を Web サイト作成の手段と考えてしまうと、コンソール アプリケーションにどのような影響があるかがわからなくなります。実際のところ、ASP.NET 5 は、アプリの実行基盤となる新しい "バージョン" の .NET Framework を提供しています。実は、現状、この新しいバージョンには 2 つのバリエーションがあり、1 つは完全版の共通言語ランタイム (CLR) 上で実行されるもので、もう 1 つは新しい CoreCLR で実行されるものです。そのうえ、近い将来、クロスプラットフォーム CLR で実行される 3 つ目のバリエーションも追加される予定です。最も効率の高いバージョンは .NET Core と呼ばれ、これも効率が高いランタイム、CoreCLR で実行されます。昔 .NET Framework を学んだころを振り返ってみると、マイクロソフトが仕様となる共通言語基盤 (CLI) を定義したことが思い出されます。その後、マイクロソフトはその CLI に基づいて CLR をビルドしました。Mono は、Linux と Mac OS X 上で実行されるもう 1 つの CLI 実装です。.NET アプリは常に、利用可能な CLI 実装に依存しています。多くの開発者は、Visual Studio と Windows を使用して、その CLR に依存する .NET アプリを作成しています。Mono 上で実行されるアプリを開発するための Xamarin の人気もますます高まっています。

CoreCLR と Entity Framework

現在、マイクロソフトは、CoreCLR という効率の高い CLI 実装を作成しています。この実装は、オープン ソースであるだけでなく、NuGet などのパッケージ マネージャーによって配布することもできます。そのため、開発者は、モバイル デバイスやクラウド ベースのサーバー アプリケーション向けに、優れた軽量のアプリを開発できるようになります。さらに、Windows コンピューターにしか配置できないという制約も取り除かれます。

Entity Framework 6 (およびそれ以前) は完全版の .NET Framework と完全版の CLR に依存し、CoreCLR をターゲットとするアプリには利用できません。しかし、EF7 は、必要な機能セットに応じて混在させたり、対応付けたりできる、小さく、構成可能な API のセットとして設計されています。たとえば、非リレーショナル データ ストアをターゲットにする場合、リレーショナル データベース用に設計されているリレーショナル機能や移行機能は必要ありません。EF7 に関係するロジックは個別の DLL に収められるため、取得してメモリに読み込む必要がなくなります。

CoreCLR をターゲットにする場合は、適切なランタイム環境を選択します。ASP.NET 5 をターゲットにするために、マイクロソフトは K Runtime Environment (KRE) を作成しました。ASP.NET MVP の Gunnar Peipman は、「K Runtime Environment (KRE) は、ASP.NET vNext アプリケーションをブートして実行するために必要なコード」と説明しています。K Runtime はリリース前に名称が変更される予定です。この変更に注意してください。たとえば、KVM (バージョン マネージャー) は DNVM (.NET Version Manager) に変更される予定です。このランタイムには、コンパイル システム、SDK ツール、ネイティブ CLR ホストなどが含まれています (bit.ly/1x9rpOn、英語)。CoreCLR をサポートする KRE には、32 ビット版と 64 ビット版があります。これらは、ASP.NET 5 アプリケーションをターゲットとするオプションと考えてかまいません (図 1 参照)。

ASP.NET 5 アプリケーションでのターゲット KRE の選
図 1 ASP.NET 5 アプリケーションでのターゲット KRE の選択

アプリケーションで EF7 を確認する最も簡単な方法は、Pluralsight コースのデモ ビデオ「Entity Framework 7 に備える」(bit.ly/18ct13F、英語) を見ることですが、それ以外に、ASP.NET 5 プロジェクト テンプレートを利用する方法があります。このテンプレートでは、EF7 を使って ID ベースの認証をアプリケーションに提供するコードが組み込まれたソリューションを利用することができます。

まず、[ASP.NET Web アプリケーション] を選択し、ASP.NET 5 Starter Web テンプレートを選択します (図 2 参照)。

Entity Framework 7 を使用して事前に構成された新しい ASP.NET 5 アプリケーションの作成
図 2 Entity Framework 7 を使用して事前に構成された新しい ASP.NET 5 アプリケーションの作成

EF7 EntityFramework.SqlServer パッケージと EntityFramework.Commands パッケージが既に選択されているのがわかります。SqlServer パッケージによって、その依存関係 (EntityFramework.Core、EntityFramework.Relational) が取り込まれます。

このことは、project.json ファイルで確認できます。このファイルの dependencies セクションに、取り込まれる NuGet のパッケージが一覧されています。このセクションの数行を以下に示します。

"dependencies": {
  "EntityFramework.SqlServer": "7.0.0-beta2",
  "EntityFramework.Commands": "7.0.0-beta2",
  "Microsoft.AspNet.Mvc": "6.0.0-beta2",

最終的な参照関係を references セクションで確認することもできます。このセクションの既定では、アプリケーションの ASP.NET 5.0 版と ASP.NET Core 5.0 版の参照関係が一覧されます。図 3 は、ASP.NET Core 5.0 の参照関係を展開した一覧を示しています。テンプレートは現在 beta2 バージョンをターゲットにしているため、Migrations パッケージが参照されているのがわかりますが、それ以降のバージョンの場合、Migrations は Relational API に含まれるようになります。

Entity Framework 7 のパッケージと API を含む ASP.NET 5.0 と ASP.NET Core 5.0 の参照関係
図 3 Entity Framework 7 のパッケージと API を含む ASP.NET 5.0 と ASP.NET Core 5.0 の参照関係

ASP.NET 5 と EF7 はどちらも、依存関係の挿入 (DI) に大きく依存します。これはプロジェクトの Startup.cs でわかります (図 4 参照)。このファイルには、アプリが使用すべき Entity Framework、SQL Server API、および ApplicationDbContext (セキュリティ目的で使用する 1 つの事前定義の DbContext) を認識させるロジックが含まれています。このファイルを確認すれば、アプリケーションに ID サービスを組み込む同様の状況に対処できます。接続文字列は config.json ファイルに格納され、Startup コンストラクターはこのファイルを利用しているため、アプリケーションでは必要なときに接続文字列を見つけることができます。

図 4 既定の Startup.cs のリストの一部

public class Startup {
  public Startup(IHostingEnvironment env) {
    Configuration = new Configuration()
      .AddJsonFile("config.json")
      .AddEnvironmentVariables();
  }
  public IConfiguration Configuration { get; set; }
  public void ConfigureServices(IServiceCollection services) {
    services.AddEntityFramework(Configuration)
      .AddSqlServer()
      .AddDbContext<ApplicationDbContext>();
    services.AddIdentity<ApplicationUser, IdentityRole>(Configuration)
      .AddEntityFrameworkStores<ApplicationDbContext>();
       services.AddMvc();  }

現在のプロジェクト テンプレートでは、既定で EF7 とそのロジックを使用するようにセットアップされています。これは、効率の高い CoreCLR をターゲットにする場合も完全版の .NET Framework をターゲットにする場合も同じです。ただし、プロジェクトの既定では CoreCLR 下で実行されるようには定義されておらず、完全版の .NET Framework を使用するように定義されています。では、このオプションが適合する状況を見てみましょう。

ASP.NET 5 向けの完全版 CLR (および Entity Framework)

.NET Framework の次期更新版は .NET Framework 4.6 です。これにより、Windows フォーム、Web フォーム、Windows Presentation Foundation (WPF)、.NET MVC 5 など、これまで作成できたあらゆるスタイルのソフトウェアを引き続き作成できるようになります。KRE-CLR-amd64 や KRE-CLR-x86 など、さまざまなバージョンの KRE (図 1 参照) により、完全版の .NET Framework 上で ASP.NET 5 アプリケーションを実行することもできます。これにより、MVC 6 や新しい Web API (MVC コントローラーと Web API の組み合わせ) など、ASP.NET 5 の新機能のメリットを生かせるようになります。また、完全版の .NET Framework と CLR をターゲットにしていると、完全版のすべての機能にアクセスできるため、旧バージョンとの互換性も確保できます。既定の project.json ファイルを見ると、以下のように、どちらのバージョンの CLR でもアプリケーションを実行できるようになっていることがわかります。

"frameworks": {
      "aspnet50": { },
      "aspnetcore50": { }
    },

"aspnetcore50" 行を (前行末尾のコンマも一緒に) 完全に削除することができます。これには 2 つの効果があります。まず、ソリューション エクスプローラーの参照セクションに ASP.NET Core 5.0 セクションが表示されなくなります。次に、図 1 に表示される KRE ターゲットが少なくなり、KRE-CLR オプションだけになります。

依然として、EF7 をターゲットにして、この新しいバージョンのメリットをすべて利用することができます。ただし、KRE-CLR は完全版の .NET Framework をターゲットにするため、Entity Framework 6 と互換性があるかどうかは明確ではありません。つまり、既存の EF6 ロジックが手元にあれば、ASP.NET 5 と組み合わせて使用でき (ただし、CoreCLR バージョンではありません)、EF6 コードを EF7 に合わせて作り直す必要なく ASP.NET 5 の新機能のメリットを生かすことができます。

ASP.NET 5 (完全版 CLR) と EF6

前述のように、この組み合わせになる可能性があることがわかったので、必然的に EF6 を取り入れる ASP.NET 5 ソリューションを試してみなければなりません。これを適切に実現するには、2015 年 2 月現在のかなり初期のバージョンと、ASP.NET 5 と Visual Studio 2015 のリリース時のバージョンとの間での変更が必要になります。

これを実現するために最も重要な要素は、Entity Framework のロジックと依存関係を、ASP.NET 5 プロジェクトとは別のプロジェクトに保持することです。いずれにせよ、通常は、このような方法でアプリケーションを設計します。アプリケーションのすべての層を 1 つのプロジェクトに含めることはしません。EF 専用の個別のプロジェクトにより、実行時に EF7 API を取り込む ASP.NET 5 アプリについて心配する必要がなくなります。

ASP.NET 5 Starter Web プロジェクトから開始するのではなく、ASP.NET Empty プロジェクト テンプレートを使用する方がよいでしょう。project.json ファイルには、Microsoft.Asp.NET.Server.IIS という依存関係が 1 つだけ指定されます。

次に、2 つ目のプロジェクトを作成します。こちらには .NET 4.6 Class Library プロジェクトを選択します。次に、パッケージ ソースとして nuget.org を指定し、既定のプロジェクトとしてこのクラス ライブラリを指定するようにして、Package Manager Console により EF6 をインストールします。ここでは、いつものように、"install-package entityframework" を呼び出すことができます。その結果、entityframework.dll と entityframework.sqlserver.dll がプロジェクトに組み込まれます。

テストのために、(EF6 を忍者版、EF7 を侍版と考え) Ninja.cs というシンプルなクラスを作成します。

public class Ninja {
    public int Id { get; set; }
    public string Name { get; set; }
  }

Ninjas の DbSet を公開する DbContext も作成します。

public class NinjaContext : DbContext {
  public NinjaContext()
    :base(@"Data Source=(localdb)\mssqllocaldb;
          Initial Catalog=NinjaContext;
          Integrated Security=True;"){ }
  public DbSet<Ninja> Ninjas { get; set; }
}

テストを簡潔にするために、SQL Server の接続文字列を DbContext クラスに直接ハードコーディングします。

モデルの定義では、いつものように、移行を有効にし、新しい移行を追加して、データベースを作成します。EF6 をデータ プロジェクトにインストールするときに、パッケージによって作成された app.config を残し、そのプロジェクトをスタートアップ プロジェクトに設定して、移行コマンドが正しく機能するようにします。また、DbMigrationsConfiguration Seed メソッドを使用して、いくつかの Ninjas をデータベースに事前シードしておきます。

ASP.NET 5 アプリケーションから直接 EF の呼び出しを行ってバージョンの混乱を招かないように、必要なクエリをカプセル化するクラスを EF6 プロジェクトに用意します。今回の目的からこのクラスを Repository としましたが、リポジトリ パターンに従うクラスではありません。これはデモ アプリや単一クエリへの課題を提示しているわけではなく、複雑なアプリの懸案事項をお気に入りのパターンを使って分離できることを示しています。

public class Repository  {
  public List<Ninja> GetAllNinjas() {
    using (var context=new NinjaContext())
    {
      return context.Ninjas.ToList();
    }
  }
}

データ アクセス プロジェクトをすべてセットアップしたら、ASP.NET 5 プロジェクトに戻り、ビューを取得して返すシンプルなコントローラーを作成します。

public class NinjaController : Controller
  {
    public IActionResult Index()
    {
      var repo = new Repository();
        return View(repo.GetAllNinjas());
      }
    }
  }

コントローラーから渡される Ninjas を一覧にするシンプルな Index.cshtml も作成します。

@model List<EF6Model.Ninja>
@{
  ViewBag.Title = "EF6 Ninjas";
}
@foreach (var item in Model)
{
  @Html.Label(item.Name);
}

最後に、MVC サービスを挿入して Ninja コントローラーへのルーティングを指定するコードを、startup.cs ファイルに追加します (図 5 参照)。

図 5 Entity Framework 6 を使用する ASP.NET 5 アプリを構成するための Startup クラス

public class Startup  {
  public void Configure(IApplicationBuilder app) {
    app.UseMvc(routes =>
    {
      routes.MapRoute(
      name: "default",
      template: "{controller}/{action}/{id?}",
      defaults: new { controller = "Ninja", action = "Index" });
     });
  }
  public void ConfigureServices(IServiceCollection services)  {
    services.AddMvc();
  }
}

また、project.json ファイルから aspnetcore50 フレームワークを削除して、完全版n CLR だけをターゲットにします。

移行によって作成したデータベースとシード データにより、ASP.NET 5 アプリが EF6 ベースのプロジェクトと連携し、EF6 を使用して取得したデータを表示するようすを確認できます (図 6 参照)。

Entity Framework 6 からのデータを表示する ASP.NET 5 アプリケーション
図 6 Entity Framework 6 からのデータを表示する ASP.NET 5 アプリケーション

EF7 と ASP.NET 5 をすぐに使用するかどうか

EF7 の新機能やそれを最大限活用する方法については非常に関心があります。また、ASP.NET 5 によって開かれる新しいプログラミング手段について理解することも楽しみです。CoreCLR は EF7 と同様に、進化するにつれてより機能が豊富になっていくでしょう。EF7 は ASP.NET 5 と共にリリースされるため、EF7 の状態には良い感触を得ています。しかし、Web 開発者ではないため、ASP.NET の試作段階でこれを運用するコードに取り組む理由はありません。また、EF チームは、プレリリースに位置付けられる初期リリースの EF7 を、ASP.NET 5 アプリケーションでのみ使用するよう推奨していることも明白です。それ以外の使い方については、正式版の EF7 がリリースされるのを待つようアドバイスしています。そのため、EF7 の今後のリリースを待つのが適切ですが、EF7 の進化に注目して実験を続け、EF6 と同等の機能を見過ごさずに利用できるようにしていきます。

今のところ CoreCLR は最先端すぎると感じています。ASP.NET 5 の完全版 CLR のリリースで利用できる機能や、EF7 プレリリースの機能セットに適合するシナリオを見つけた場合は、そちらのパスを利用しますが、多くの場合は今後のリリースを待つか、ASP.NET 5や CoreCLR の機能が豊富になるのを待つことになるでしょう。その時までは、個人的に、今後のリリースに備えてこのようなツールを調査して学習するチャンスを提供する予定です。

それまでの間、Scott Guthrie のブログ投稿「Introducing ASP.NET 5」(ASP.NET 5 の概要、bit.ly/1wV4zzm、英語) を参考にして、ASP.NET 5 によってもたらされるすべての新機能について理解を深めておいてください。構成可能な API は、この変化の過程で開発者が利用可能になる数ある機能拡張の 1 つにすぎません。


Julie Lerman は、バーモント ヒルズ在住の Microsoft MVP、.NET の指導者、およびコンサルタントです。世界中のユーザー グループやカンファレンスで、データ アクセスなどの .NET トピックについてプレゼンテーションを行っています。彼女のブログは thedatafarm.com/blog (英語) で、彼女は O'Reilly Media から出版されている『Programming Entity Framework』(2010 年) および『Code First』版 (2011 年)、『DbContext』版 (2012 年) を執筆しています。彼女の Twitter (twitter.com/julielerman、英語) をフォローして、juliel.me/PS-Videos (英語) で彼女の Pluralsight コースをご覧ください。

この記事のレビューに協力してくれた技術スタッフの Rick Byers に心より感謝いたします。
Rick Strahl は、ハワイの美しいマウイ島にある West Wind Technologies の実力者であり、優れたサーファーでもあります。ウィンドサーフィンの活動とツンツン頭の冒険の合間に、25 年間ソフトウェア開発者として働き、手回し機 (または一組の配線接合機) を必要とした Web の黎明期から、ビジネス アプリケーションや Web アプリケーションをビルドしてきました。現在は、HTML5、JavaScript、モバイル Web テクノロジを使用する顧客のために、フロントエンドでは AngularJS を使用し、バックエンドでは ASP.NET スタックやマイクロソフト テクノロジを使用して、クライアント中心の Web アプリケーションやサービスをビルドしています。彼の会社 West Wind Technologies は、Wind WebSurge、West Wind Web Monitor、Html Help Builder など、開発者関連の多くのツールを生産しています。また、github.com/RickStrahl (英語) でオープンソースのライブラリをホストしています。彼のブログは weblog.west-wind.com (英語) で公開されています。連絡先は rstrahl@west-wind.com (英語のみ) です。