.NET Core上でLINQを使ってMySQLにアクセスする

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

カテゴリー: 開発, C# パーマリンク