(すべてではないにしても)ほとんどのビジネスロジックが独自のレイヤーに常駐する必要があることはわかっていますが、いくつかの基本的なビジネスロジックをリポジトリレイヤー自体の中に配置することの一般的なコンセンサスは何ですか?
私のシナリオ:オプションの列がいくつかあるテーブルがありますが、列の1つに値が含まれている場合、他の2つはその値の影響を受けます。
そのテーブルのエンティティのPOCOは次のようになります。
public class Template
{
public int Id {get;set;}
public string MessageTemplate {get;set;}
public int? FacilityId {get;set;}
public int? ResourceId {get;set;}
public bit GlobalDefault {get;set;}
}
これで、グローバルデフォルトとして指定されたエントリは1つだけになり、同様に、各施設またはリソースはテーブルに1回だけリストされます。後者の制約はSQL Serverによって強制されますが、すべてがスムーズに流れるようにするには、ビジネスロジックが必要です。
このテーブルの場合、既存の施設またはリソースの新しいレコードを挿入しようとすると、以前のレコードが代わりに更新(または削除)されます。新しいグローバルデフォルトを設定する場合も同様です。 1つのエンティティのみをグローバルデフォルトにする必要があるため、別のエンティティが存在する場合は、代わりに削除または更新する必要があります。
明らかに、私のビジネスレイヤーはこれらのシナリオを可能な限り処理しますが、リポジトリ自体にそのレベルのロジックを実装することはどれほど不快なことでしょうか。
私のリポジトリでは次のようなものを想定しています:
public void InsertFacilityTemplate(Template template)
{
var existing = context.Templates.Where(n => n.FacilityId == template.FacilityId);
Template recordToSave;
if (existing.Count > 1)
DeleteRecords(existing);
if (existing.Count == 1)
recordToSave= existing.First();
if (recordToSave != null)
{
recordToSave.MessageTemplate = template.MessageTemplate;
Update(recordToSave);
}
else
Insert(template);
}
ここで適切なアプローチは何ですか?
データベースとメソッドでは、OR存在に基づいて更新する)を挿入するアクションにupsertという用語を使用することがよくあります。リポジトリのupsertメソッド。
他の場所で挿入/更新ロジックについて繰り返しについて質問しているか、またはwhereについて質問しているかどうかは、説明から明確ではありませんこのロジック(つまり、メソッドの例)。
RemoveDuplicateInstances(ITemplate template)
やPrepareUpsert(string templateId)
など、アップサートの準備をより明確にする別のメソッドを呼び出すことを検討してください。また、この例では更新されたフィールドが何であるかを知っていると想定しています。たとえば、GlobalDefault値が切り替えられた場合、または別のフィールドがクラスに追加された場合、Insertはそれらの変更を保持しますが、Updateへのロジックは保持しません。それは期待と矛盾した行動です。これらの懸念は言われていますが、アプリケーションが小さい、概念実証、または非常に単純な場合、これらの変更は非常に小さいため、機能的には違いがありません。あなたの後に誰かが来たり、このコードベースを拡張し続けるつもりである場合、それは違います。
問題の根本は 貧血ドメインモデル のようです。データモデルを表すPOCOクラスを使用することに問題はありません。解決しようとしている問題は、次のビジネスルールに由来します。
「施設」は、その施設の各テンプレートが一意の「リソース」を参照している限り、複数のテンプレートを持つことができます。
ファシリティのテンプレートのうち1つだけを「グローバルデフォルト」にする必要があります。
これらのルールを前提として、このファシリティを「施設」とそのすべての「テンプレート」を処理するクラスにプッシュする必要があります。
何かのようなもの:
var facility = // get by facility Id
var template = new Template() { /* initialize properties */ };
facility.SetGlobalTemplate(template);
次に、SetGlobalTemplateメソッドは、その機能に関連付けられたテンプレートをループし、それに応じてビットフラグを設定します。
次に、「リポジトリ」は新しい施設を保存するだけです。データマッピングが新しいテンプレートと以前のグローバルテンプレートへの更新を取得できることを確認してください。中途半端なORMはこれを実行できる必要があります(Entity Framework、NHibernateなど)。
repository.SaveFacility(facility);