次のエンティティを持つシステムがあるとします。
public class Doctor
{
public int ID { get; set; }
public int DepartmentID { get; set; }
public string Name { get; set; }
public ICollection<Recipe> Recipes { get; set; }
}
public class Patient
{
public int ID { get; set; }
public string Name { get; set; }
public ICollection<Recipe> Recipes { get; set; }
}
public class Recipe
{
public int ID { get; set; }
public int DoctorID { get; set; }
public int PatientID { get; set; }
public Doctor Doctor { get; set; }
public Patient Patient { get; set; }
public ICollection<RecipeDetails> Details { get; set; }
}
public class RecipeDetails
{
public int ID { get; set; }
public Guid SomeGuid { get; set; }
public double SomeValue { get; set; }
}
また、要件があります。
- 医師は自分のレシピを編集できるはずです
- 医師は、自分の部門内の医師からのレシピのみを表示できるようにする必要があります
- 医師は、利用可能なレシピで検索を実行できる必要があります
- 医師は、利用可能なレシピの詳細によってレポートを生成できる必要があります
今のところ、次のセキュリティ チェックを実装しました。
public void ValidateAccess(Doctor doctor, Recipe aRecipe, EntityAction action)
{
if (action == EntityAction.Modify && doctor.ID == aRecipe.Doctor.ID)
return;
if (action == EntityAction.Read && doctor.DepartmentID == aRecipe.Doctor.DepartmentID)
return
throw new SecurityException();
}
これは、受信エンティティがある場合の単純なメソッドに最適です。ロジック メソッドの先頭でこのメソッドを呼び出すことで、アクセスを簡単に検証できます。
しかし、今私は問題を抱えています.正確なエンティティを持っていないが、いくつかの統計がある場合、このソリューションは検索とレポートでは機能しません。
コンポーネント「someGuid」を持つレシートを持つ名前「aName」の患者のレポートを生成したいと想像してみましょう。2 つの基準を持つクエリがあります。
var res = RecipeRepository.Query(r => aName.Contains(r.Patient.Name)).SelectMany(r => r.Details).Where(d => d.SomeGuid == someGuid).Sum(d => d.SomeValue);
このクエリは正しくありません。非表示にするレシピを含むすべてのレシピの統計が表示されます。これを修正するには、クエリにアクセス条件を追加する必要があります。
currentDoctor.DepartmentID == r.Doctor.DepartmentID
だから今私はクエリを持っています:
var res = RecipeRepository.Query(r => aName.Contains(r.Patient.Name) && currentDoctor.DepartmentID == r.Doctor.DepartmentID).SelectMany(r => r.Details).Where(d => d.SomeGuid == someGuid).Sum(d => d.SomeValue);
問題は、領収書の計算を行うシステム内の各クエリにこの部分を追加する必要があることです。
更新 (2012 年 11 月 12 日):
最初の例は非常に単純で、StuartLC が投稿で述べたように解決できます。しかし、私たちのシステムにはもっと複雑なレポートがあります。たとえば、レシピにコンポーネント someGuid を持つすべての患者を表示します。ここで、クエリは別のリポジトリから開始されるため、RecipeRepository のプライベート メソッドまたは保護されたメソッドを適用できません。サンプルクエリは次のとおりです。
var res = PatientRepository.Query(p => p.Name.Contains(aName) && p.Recipes.Any(r => r.Details.Any(d => d.SomeGuid == someGuid)));
この場合、フィルターをクエリに直接追加する必要があります。
var res = PatientRepository.Query(p => p.Name.Contains(aName) && p.Recipes.Any(r => currentDoctor.DepartmentID == r.Doctor.DepartmentID && r.Details.Any(d => d.SomeGuid == someGuid)));
更新を終了します。
このソリューションをより簡単にし、各クエリへの式のコピーと貼り付けを防ぐために適用できるパターンまたはプラクティスは何ですか? 回答とアドバイスをいただければ幸いです。