Windows上では、Visual Studioを使ってデザイナを使いながらMySQLからテーブル構造を引っ張ってこれるのだが、じゃあ、.NET Core の場合はどうするのか?
多分、マイグレーション機能を使って、MySql.Data.EntityFrameworkCore.Design あたりを NuGet でとってきてあれこれやるんだろうだが、面倒なので。
- あらかじめ、Windows の EF デザイナで取得したクラスを取ってくる。
- 手作業でテーブルクラスを作る
のどちらかがよい。
Redmine のプロジェクト(projects)とチケット(issues)は、こんな風になっている。これ自体は、Windows 上の .NET でも使えるし、Linux 上の .NET Core でも使える。
public class projects { public int id { get; set; } public string name { get; set; } public string description { get; set; } public string homepage { get; set; } public int is_public { get; set; } public int? parent_id { get; set; } public DateTime? created_on { get; set; } public DateTime? updated_on { get; set; } public string identifier { get; set; } public int status { get; set; } public int? lft { get; set; } public int? rgt { get; set; } public int inherit_members { get; set; } public int? default_version_id { get; set; } } public class issues { public int id { get; set; } public int tracker_id { get; set; } public int project_id { get; set; } public string subject { get; set; } public string description { get; set; } public DateTime? due_date { get; set; } public int? category_id { get; set; } public int status_id { get; set; } public int? assigned_to_id { get; set; } public int priority_id { get; set; } public int? fixed_version_id { get; set; } public int author_id { get; set; } public int lock_version { get; set; } public DateTime? created_on { get; set; } public DateTime? updated_on { get; set; } public DateTime? start_date { get; set; } public int done_ratio { get; set; } public double? estimated_hours { get; set; } public int? parent_id { get; set; } public int? root_id { get; set; } public int? lft { get; set; } public int? rgt { get; set; } public int is_private { get; set; } public DateTime? closed_on { get; set; } }
ちなみに、Visual Studio の EF デザイナだと、こんな projects クラスを吐き出す。アノテーションがついているので、asp.net mvc でスキャフォールディングするときに便利っぽい感じが…するが、まあなくても大丈夫
[Table("redmine.projects")] public partial class projects { public int id { get; set; } [Required] [StringLength(255)] public string name { get; set; } [Column(TypeName = "text")] [StringLength(65535)] public string description { get; set; } [StringLength(255)] public string homepage { get; set; } public bool is_public { get; set; } public int? parent_id { get; set; } public DateTime? created_on { get; set; } public DateTime? updated_on { get; set; } [StringLength(255)] public string identifier { get; set; } public int status { get; set; } public int? lft { get; set; } public int? rgt { get; set; } public bool inherit_members { get; set; } public int? default_version_id { get; set; } }
いわゆる、Entities なクラスはどうするかというと、NuGet で「MySql.Data.EntityFrameworkCore」を入れた後に、こんな風に手作業で作る。
public partial class RedmineEntities : DbContext { public RedmineEntities() { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); optionsBuilder.UseMySQL(@"server=localhost;user id=redmine;password=redmine;database=redmine;port=3306;sslmode=None"); } public DbSet<projects> projects { get; set; } public DbSet<issues> issues { get; set; } }
Windows 上の DbContext と違うのは、データベースに接続するための設定が OnConfiguring メソッドをオーバライドして書くことになる。MySQL の場合は UseMySQL メソッドで指定する。この部分は拡張メソッドになっていて、インターフェースを決めるのではなくて、ダックタイピングなところが興味深いところ。以前は Factory だったような気もするのだが、こんな風にメソッド名でなんとなくルールを決めておくのが実に C# っぽい。
ここまで出来たら、後は .NET Core のコンソールアプリを作る。
class Program { static void Main(string[] args) { Console.WriteLine("Hello MysQL EF "); var ent = new RedmineEntities(); var items = ent.projects.ToList(); foreach (var it in items) { Console.WriteLine($"{it.id} {it.identifier} {it.name}"); } } }
シンプルに Redmine のプロジェクト一覧を表示しているだけなのだが、LINQ が使えるので SQL 文を書く必要がない。このぐらいの SELECT だと、普通に SQL 文を書いても手間は変わらないのだけど、Update とか Insert とかをやり始めると、ent.SaveChanges() で一発で書き込めるのは結構便利だったりする。特に、カラムの数が多い場合とか。
これを .net core の asp.net mvc で web api 化すると便利だったりするのだが、ターミナルを使ってコマンドラインで打てるのもよいだろう。GUI 絡みは .NET Core ではできないので、別途 Windows から MySQL のあるサーバーに繋げて、WPF で書くのがベターだろう。