Skip to content

EF Core

  • [Required] EF Core固有のAPI、relational mapping、change tracking、transaction semanticsはこのreferenceに閉じる。作業対象に該当するarchitecture、application、persistence、runtime規約を併用し、このreferenceではEF CoreとRDB固有の差分だけを扱う。

Boundary and Mapping

  • [Required] DbContextDbSet<T>IQueryable<T>EntityEntry<T>などEF Core固有型をFeatures側へ漏らさない。
  • [Required] table名、column名、key、index、relation、conversion、concurrency tokenはInfrastructureのIEntityTypeConfiguration<T>に定義し、domain modelをprovider属性へ依存させない。
  • [Required] Value ObjectはValueConverterまたはInfrastructureの永続化modelとのmappingでRDBが保存できる型へ変換する。
  • [Contextual] domain modelをEF Core entityとして直接materializeする場合は、constructor、backing field、owned typeなどのmappingをInfrastructureに閉じ、永続化都合のpublic setterを追加しない。
  • [Contextual] schemaとdomain modelの形が大きく異なる場合はInfrastructureに永続化modelを置き、repository境界で相互変換する。
  • [Required] repository portからIQueryable<T>を返さない。queryの組み立てと実行はInfrastructureに閉じ、use caseが必要とする結果を返す。

DbContext and Tracking

  • [Required] DbContextはunit of workとして短命に扱い、singletonにしない。同一transactionで行う処理は同一instanceを使う。
  • [Required] queryとSaveChangesAsyncには受け取ったCancellationTokenを渡す。
  • [Recommended] 更新しないqueryはAsNoTrackingを使う。更新対象を同じDbContextで読み書きする場合はtrackingを利用してよい。
  • [Required] lazy loadingを暗黙の初期値にしない。必要なrelationはIncludeまたはprojectionで明示し、意図しないN+1 queryを避ける。
  • [Recommended] 読み取り専用queryは必要なcolumnとshapeへprojectionし、aggregate全体を目的なくmaterializeしない。

Concurrency and Transaction

  • [Required] SaveChangesAsyncはuse caseのtransaction boundary内で呼び、repositoryごとに独立してcommitしない。
  • [Contextual] 1回のSaveChangesAsyncで必要な変更をatomicに保存できる場合は、明示的なtransactionを追加しない。
  • [Contextual] 複数回のSaveChangesAsync、raw SQL、または複数adapterのDB操作を同じtransactionへ束ねる場合は、persistence規約のuse case固有TransactionをEF Core transactionで実装する。
  • [Required] optimistic concurrencyを使うaggregateにはrow versionなどのconcurrency tokenをmappingし、DbUpdateConcurrencyExceptionをInfrastructureで捕捉してuse caseが判断できるpersistence resultへ変換する。
  • [Required] unique constraintやforeign key違反を業務結果として扱う場合は、provider固有例外をFeaturesへ漏らさず、識別可能なpersistence resultへ変換する。
  • [Required] retryされ得るtransactionまたはexecution strategy内で、メール、通知、決済、外部APIなどの外部副作用を実行しない。
  • [Contextual] DB更新と確実な外部副作用の連携が必要なら、同じtransactionでOutbox recordを保存し、冪等な別処理で配送する。

Migrations and SQL

  • [Required] migrationはschema変更のartifactとしてInfrastructure側で管理し、domainまたはFeaturesの責務にしない。
  • [Required] production起動時にmigrationを自動適用するか、deployment stepで適用するかは運用要件として明示し、暗黙に選ばない。
  • [Contextual] raw SQLを使う場合はparameter bindingを使い、入力値を文字列連結しない。戻り値とtransactionはrepository contractに従わせる。
  • [Contextual] provider固有SQL、index、locking hintを採用する場合は、必要な整合性または性能上の根拠を設計資料に残す。