エンティティがリポジトリにアクセスしても問題ありませんか?
いいえ、しないでください。
まず、ドメイン モデルの考え方は、アプリケーションからビジネス ロジックを分離することです。データベース、リポジトリ、およびアプリケーションから分離します。これにより、ビジネス ロジックを分離したままにしておくことができ、アプリケーションとは別にテストおよび変更できるようになります。
ドメインはデータの永続性を完全に認識しておらず、それが自動的に発生すると想定する必要があります。
ddd-the-repository-pattern.aspx
第二に、リポジトリをエンティティに挿入しない、より実用的な理由が他にもあります。
リポジトリへの依存関係を作成したエンティティにリポジトリを挿入することにより、エンティティは単体テスト可能である必要があります。
GetInstance() メソッドを使用すると、デメテルの法則が破られ、ITaskStatusRepository とエンティティとの密結合が作成されます。つまり、新しいタスクを作成して単体テストを作成する場合、タスクが ITaskStatusRepository を必要とすることは構築時に明らかではありません。これにより、ビジネス ロジックの単体テストがより困難になります。
DDD の観点から見ると、リポジトリは DB とのインターフェイスだけでなく、インメモリ ストアからの取得にも関係しています。またはリスト。
リポジトリはテーブルと 1 対 1 の関係である必要はありません。タスク リポジトリで他のテーブルとの内部結合を実行して複雑なクエリを実行する必要があり、タスク アイテムのリストを返す場合は、そのクエリを実行するリポジトリからメソッドを公開します。(これは、リポジトリ パターンの一般的な誤解だと思います)。
エンティティは、データベースでアクションを実行することに関心を持つべきではありません。
ここに投稿された画像を参照してください:
DDD: レイヤーをどのように編成する必要がありますか?
public class TaskStatus
{
public long Id { get; set; }
public string Description { get; set; }
public TaskStatus() {
Description = "Incomplete";
}
}
public class Task
{
public long Id {get;set;}
public string Description {get;set;}
public TaskStatus Status {get;set;}
public void CompleteTask()
{
Status.Description = "Complete";
}
}
アプリケーション層内では、リポジトリが永続性を担当します (またはしない)。リポジトリは、集約ルートの List<> です。また、集約ルート レベルで機能します。
TaskService 内で Task を使用する例。サービスは、アプリケーション層のエンティティに作用します。
public class TaskService
{
private readonly ITaskRepository _taskRepository;
public TaskService(ItaskRepository taskRepository){
_taskRepository = taskRepository;
}
public List<Task> CompleteAllTasks()
{
List<Tasks> getTasks = _taskRepository.GetTasks();
getTasks.ForEach(CompleteTask);
return _taskRepository.Save(getTasks);
}
}