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 で書くのがベターだろう。

