BLL
- Nuget
- Oracle.EntityFrameworkCore
- Oracle.ManagedDataAccess.Core
DbModelBase
ConcurrencyCheck:ータが更新される際に、データベースのバージョンがメモリ上のバージョンと一致しているかを確認し、不一致の場合はDbUpdateConcurrencyExceptionをスローする。
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; public interface IDbModelBase { int Idno { get; set; } DateTime CreatedAt { get; set; } DateTime UpdatedAt { get; set; } int VersionNo { get; set; } string? IsActive { get; set; } } public class DbModelBase : IDbModelBase { [Column("IDNO"), Key] public int Idno { get; set; } [Column("CREATED_AT")] public DateTime CreatedAt { get; set; } [Column("UPDATED_AT")] public DateTime UpdatedAt { get; set; } [Column("VERSION_NO"), ConcurrencyCheck] public int VersionNo { get; set; } [Column("IS_ACTIVE")] public string? IsActive { get; set; } }
DbContext
OnBeforeSavingで共通項目の自動設定を行える。
public class AppDbContext : DbContext { public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) {} protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); } public override int SaveChanges() { OnBeforeSaving(); return base.SaveChanges(); } public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default) { OnBeforeSaving(); return base.SaveChangesAsync(cancellationToken); } private void OnBeforeSaving() { var entries = ChangeTracker.Entries<IDbModelBase>(); foreach (var entry in entries) { if (entry.State == EntityState.Added) { entry.Entity.CreatedAt = DateTime.UtcNow; entry.Entity.UpdatedAt = DateTime.UtcNow; } else if (entry.State == EntityState.Modified) { // 更新時、CreatedAtは変更しない entry.Property(p => p.CreatedAt).IsModified = false; entry.Entity.UpdatedAt = DateTime.UtcNow; } } } }
try-catchで処理する
try { var product = _context.Products.Find(1); // データを取得 if (product == null) { // 処理なし } product.Price = 12.34m; // データを変更 _context.SaveChanges(); // 楽観的ロックチェック } catch (DbUpdateConcurrencyException ex) { // 競合が発生した場合の処理 // 例: ユーザーにエラーメッセージを表示し、再ロードを促す // データベース上の最新の値を画面に表示するなど }
IDENTITY
modelBuilder.HasSequence<int>("USER_SEQ", schema: "YOUR_SCHEMA") .StartsAt(1) .IncrementsBy(1); modelBuilder.Entity<User>() .Property(u => u.Id) .HasDefaultValueSql("USER_SEQ.NEXTVAL");
Index宣言
[Index(nameof(Email), IsUnique = true, Name = "IDX_USER_EMAIL")] public class User { public int Id { get; set; } public string Email { get; set; } }
Web API
コードファストのマイグレーションコマンドは WebAPI プロジェクトを起点に実行する必要があり * Nuget - Oracle.EntityFrameworkCore - Oracle.ManagedDataAccess.Core - Microsoft.EntityFrameworkCore.Design - Swashbuckle.AspNetCore - 参照 - BLL
Appsetting.json
{ "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "OracleDbContext": "User Id=ORCL;Password=ORCL;Data Source=localhost/ORCL;" } }
Program.cs
builder.Services.AddDbContext<AppDbContext>(options => options.UseOracle(builder.Configuration.GetConnectionString("OracleDbContext")));
Controller
DIされたAppDbContextをコントローラの初期化時に取得する。
[ApiController] [Route("[controller]")] public class MyController : ControllerBase { private readonly AppDbContext _context; public MyController(AppDbContext context) { _context = context; } }
マイグレーション
プロジェクトにEF Coreのツールを追加
dotnet add package Microsoft.EntityFrameworkCore.Design
Visual Studio → ツール → NuGet パッケージマネージャー → パッケージマネージャー コンソール
Add-Migration InitialCreate Update-Database Remove-Migration
.net cliの場合
dotnet tool install --global dotnet-ef dotnet ef migrations add InitialCreate \ --project pjname \ --startup-project pjname dotnet ef migrations add InitialCreate dotnet ef database update dotnet ef migrations remove
出力する場合
dotnet ef migrations add InitialCreate \ --project rf_bll \ --startup-project rf_api \ --output-dir Migrations
クライントにOpen APIサービス追加
追加 サービス参照 OpenAPI
クライアントを生成
var sc = new rf_api_client("http://localhost:5086", new HttpClient()); ICollection<WeatherForecast> forecasts = await sc.GetWeatherForecastAsync(); foreach (var forecast in forecasts) { MessageBox.Show($"Date: {forecast.Date}, TempC: {forecast.TemperatureC}, Summary: {forecast.Summary}"); }
SQL 実行
sqlplus myuser/mypassword@localhost/ORCL @"C:\scripts\init_schema.sql"