.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 でも使える。

[code lang=”csharp”]
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; }
}
[/code]

ちなみに、Visual Studio の EF デザイナだと、こんな projects クラスを吐き出す。アノテーションがついているので、asp.net mvc でスキャフォールディングするときに便利っぽい感じが…するが、まあなくても大丈夫

[code lang=”csharp”]
[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; }
}
[/code]

いわゆる、Entities なクラスはどうするかというと、NuGet で「MySql.Data.EntityFrameworkCore」を入れた後に、こんな風に手作業で作る。

[code lang=”csharp”]
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; }
}
[/code]

Windows 上の DbContext と違うのは、データベースに接続するための設定が OnConfiguring メソッドをオーバライドして書くことになる。MySQL の場合は UseMySQL メソッドで指定する。この部分は拡張メソッドになっていて、インターフェースを決めるのではなくて、ダックタイピングなところが興味深いところ。以前は Factory だったような気もするのだが、こんな風にメソッド名でなんとなくルールを決めておくのが実に C# っぽい。

ここまで出来たら、後は .NET Core のコンソールアプリを作る。

[code lang=”csharp”]
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}");
}
}
}
[/code]

シンプルに Redmine のプロジェクト一覧を表示しているだけなのだが、LINQ が使えるので SQL 文を書く必要がない。このぐらいの SELECT だと、普通に SQL 文を書いても手間は変わらないのだけど、Update とか Insert とかをやり始めると、ent.SaveChanges() で一発で書き込めるのは結構便利だったりする。特に、カラムの数が多い場合とか。

これを .net core の asp.net mvc で web api 化すると便利だったりするのだが、ターミナルを使ってコマンドラインで打てるのもよいだろう。GUI 絡みは .NET Core ではできないので、別途 Windows から MySQL のあるサーバーに繋げて、WPF で書くのがベターだろう。

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