EntityFrameworkのデータファーストとDbContextの接続文字列を動的に変える方法
EntityFrameworkはAsp.NET MVCのO/Rマッパーです。
ユーザが Model クラスを作成し、 ビルド時にそれを元にEntityFrameworkがDBとテーブルを作成します。 コードからDBが作成されるので通常これはコードファーストと呼ばれます。
しかし、既存のDBからModelを自動生成する方法もEntityFrameworkには用意されています。 (実際の業務ではこっちの方が多い気がしますね。) これは、DBからコード(Model)を作るのでデータファースと呼ばれます。
DBからModelを作成する方法
では、データファーストにより既存のDBからModelを作成する方法を紹介します。
0.事前準備
ソリューションにDBを作成します。 今回はDB名を TestDB、その中にテーブル:users を用意しておきます。
CREATE TABLE [dbo].[users] ( [Id] INT NOT NULL, [name] NCHAR (10) NULL, [age] NCHAR (10) NULL, [sex] NCHAR (10) NULL, PRIMARY KEY CLUSTERED ([Id] ASC) );
1.プロジェクト内にModelsフォルダを作成します。
2.Modelsフォルダで右クリックし「新しい項目を追加」を選択します。
3.「ADO.NET Entity Data Model」を追加します。
名前は適当なものを入力します(ここではTestDBContext)。
最後に DBContext をつけるのが一般的です。
4.「データベースからCode Firstを選択。」
5.「新しい接続」をクリックして、
今回はソリューション内にDBを作ったので、データソースに「Micorosoft SQLServerデータソースファイルを選択」。
データベースファイル名には事前にソリューション内に用意しておいたDBを選択します。
6. 接続設定に名前をつけて次へ。
7.モデルを生成する対象のテーブルをすべて選択します。
8.ModelsフォルダにTestDBContextと各テーブルのModelクラスが追加されます。
できたクラスの中身はこんな感じ。
namespace DBFirstPractice.Models { using System; using System.Data.Entity; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; public partial class TestDBContext : DbContext { public TestDBContext() : base("name=TestDBContext") { } public virtual DbSet<user> users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<user>() .Property(e => e.name) .IsFixedLength(); modelBuilder.Entity<user>() .Property(e => e.age) .IsFixedLength(); modelBuilder.Entity<user>() .Property(e => e.sex) .IsFixedLength(); } } }
namespace DBFirstPractice.Models { using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; using System.Data.Entity.Spatial; public partial class user { [DatabaseGenerated(DatabaseGeneratedOption.None)] public int Id { get; set; } [StringLength(10)] public string name { get; set; } [StringLength(10)] public string age { get; set; } [StringLength(10)] public string sex { get; set; } } }
DBContextの接続文字列を動的に変える方法
下記のようにすることで、 ソース上で動的に接続先を変えることもできます。 (先ほど作成した、users テーブルと同じ構造のテーブルを持つ、 TestDbBackupというDBがあるものとします。)
まず、自動生成されたDBContextのコンストラクタを下記のように変更します。
namespace DBFirstPractice.Models { using System; using System.Data.Entity; using System.Data.Common; using System.ComponentModel.DataAnnotations.Schema; using System.Linq; public partial class TestDBContext : DbContext { public TestDBContext(DbConnection connection) : base(connection, true) { } public virtual DbSet<user> users { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<user>() .Property(e => e.name) .IsFixedLength(); modelBuilder.Entity<user>() .Property(e => e.age) .IsFixedLength(); modelBuilder.Entity<user>() .Property(e => e.sex) .IsFixedLength(); } } }
次に、DBContextをインスタンスを生成する際にConnectionを設定します。
namespace DBFirstPractice.Controllers { public class HomeController : Controller { TestDBContext _db; public HomeController() { var connection = DbProviderFactories.GetFactory("System.Data.SqlClient").CreateConnection(); connection.ConnectionString = "data source=(LocalDB)\\MSSQLLocalDB;attachdbfilename=|DataDirectory|\\TestDbBackup.mdf;integrated security=True;connect timeout=30;MultipleActiveResultSets=True;App=EntityFramework"; _db = new TestDBContext(connection); } // GET: Home public ActionResult Index() { List<user> mans = _db.users.Where(u => u.sex == "man").ToList(); return View(); } } }
この接続文字列のDataSourceを変更することでソース上で動的に接続するDBを切り替えることができます。