はじめに
初めて.NET Core と MySQL でデータベースを扱うことになったので備忘録として残そうと思います。
今回作ったサンプル
参考にしたサイト
環境
- MySQL 8.0.19
- .NET Core 3.1
テスト用のテーブルをMySQLから作成
- server: localhost
- user: root
- password: password
- database: mydb
テーブル作成。
テーブル名に複数形のsをつけないと文法エラーが出るようです。
CREATE TABLE IF NOT EXISTS products (
id INT,
name VARCHAR(32) NOT NULL UNIQUE,
price INT NOT NULL,
quantity INT NOT NULL,
PRIMARY KEY (id)
);
新規プロジェクト作成
.NET Core のコンソールアプリケーションのプロジェクトを作成します。
$ dotnet new console
MySql.Data.EntityFrameworkCore をインストール。
$ dotnet add package MySql.Data.EntityFrameworkCore
$ dotnet restore
.csproj
一応載せておきます。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MySql.Data.EntityFrameworkCore" Version="8.0.19" />
</ItemGroup>
</Project>
中身
次のクラスを作ります。
- テーブルのカラムと同じプロパティを持つEntityクラス
- オブジェクトの状態とデータベースを結びつけるDbContextクラス
- 上の2つを使って実際に操作の指示を出すメソッドを持つDataOperationクラス
それぞれ載せておきます。
Entityクラス
※今回真偽値は使っていませんが、booleanはMySQLのデータ型にないのでマップできません。bit(1)を使うとよいそうです。( 参考 )
public class Product
{
public int id { get; set; }
public string name { get; set; }
public int price { get; set; }
public int quantity { get; set; }
}
DbContextクラス
Microsoft.EntityFrameworkCore.DbContextクラスを継承します。
DbSet<>
の要素がEntityクラスで定義したものになります。
※UseMySQL()
内を適切に書き換えてください。直書きですみません...。
public class GreengrocerContext : DbContext
{
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseMySQL(@"server=localhost;database=mydb;userid=root;pwd=password;sslmode=none;");
}
DataOperationクラス
基本的な操作のメソッドをいくつか作ってみました。
※LINQのAny()
を使おうとすると、エラーが出ます。( 詳細 )
FindOrDefault()
がnull
かどうかを調べることで同じことができます。
※AsNoTracking()
すると、オブジェクトの状態をデータベースに反映させません。データベースを参照するだけのときは、入れたほうが効率的だそうです。( 詳細 )
public class DataOperation : IDisposable
{
private readonly GreengrocerContext context = new GreengrocerContext();
public DataOperation(GreengrocerContext context)
{
this.context = context;
}
public void Dispose()
{
context.Dispose();
}
//データの挿入
public void AddProduct(int id, string name, int price, int quantity)
{
Product newProduct = new Product
{
id = id,
name = name,
price = price,
quantity = quantity
};
context.Products.Add(newProduct);
context.SaveChanges();
}
//データの削除
public void RemoveProduct(int id)
{
Product product = context.Products.FirstOrDefault(x => x.id == id);
if (product != null)
{
context.Products.Remove(product);
context.SaveChanges();
}
}
//データの更新
public void UpdateProductToHalfPrice(int id)
{
Product product = context.Products.FirstOrDefault(x => x.id == id);
if (product != null)
{
product.price /= 2;
context.SaveChanges();
}
}
//全データの取得
public List<Product> GetAllProducts()
{
return context.Products.ToList();
}
//特定のデータの取得
public Product GetSingleProduct(string name)
{
return context.Products.AsNoTracking().FirstOrDefault(x => x.name == name);
}
//特定のデータの存在確認 ※Any()は使えません!!
public bool AnyProducts(string name) {
return context.Products.AsNoTracking().FirstOrDefault(x => x.name == name) != null;
}
//特定のデータの個数
public int CountProductAlmostOutOfStock()
{
return context.Products.Count(x => x.quantity < 10);
}
}
これらのクラスの使用例
データを追加して、それを出力してみます。
class Program
{
static void Main()
{
GreengrocerContext context = new GreengrocerContext();
using DataOperation dataOpration = new DataOperation(context);
dataOpration.AddProduct(1, "Tomato ", 100, 30);
dataOpration.AddProduct(2, "Cucumber", 40, 50);
dataOpration.AddProduct(3, "Onion ", 50, 100);
dataOpration.AddProduct(4, "Eggplant", 80, 20);
List<Product> products = dataOpration.GetAllProducts();
Console.WriteLine("ID\tName \tPrice\tQuantity");
foreach (Product product in products)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}", product.id, product.name, product.price, product.quantity);
}
}
}
以上です。
ご指摘、アドバイスなど歓迎いたします。