私はMVCとEFの世界にかなり慣れていないので、自分でかなりの方法でやって来ましたが、オンラインで見つけることができなかったことの1つは、人々が「削除しない」条件を検証する方法です。
DbContextT4テンプレートで生成されたEF4.1データベースファーストのPOCOクラスを使用しています。部分的なクラスファイルでは、標準のMetaData属性タイプの検証を超えるビジネスルールの変更時に呼び出される「IValidatableObject」インターフェイスですべてのクラスをすでに装飾しています。
私が今必要としているのは、削除がOKかどうかをチェックするために同じメカニズムを介して機能する(したがって、UIとコントローラーに対して透過的である)検証です。私の考えは、次のようなインターフェイスを作成することでした。
public interface IDeletionValidation
{
DbEntityValidationResult ValidateDeletion(DbEntityValidationResult validationResults);
}
...そして、DbContextのValidateEntityへのオーバーライドでこれを行います...
public partial class MyEntityContext
{
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
DbEntityValidationResult val = base.ValidateEntity(entityEntry, items);
if (entityEntry.State == EntityState.Deleted)
{
IDeletionValidation delValidationEntity = entityEntry.Entity as IDeletionValidation;
if (delValidationEntity != null)
val = delValidationEntity.ValidateDeletion(val);
}
return val;
}
...そして、安全に削除する前に検証を行う必要があるクラスにIDeletionValidationインターフェイスを実装できます。
ValidateDeletionコードの例(機能していません。コメントの警告を参照)は...
public partial class SalesOrder : IDeletionValidation, IValidatableObject
{
public DbEntityValidationResult ValidateDeletion(DbEntityValidationResult validations)
{
// A paid SalesOrder cannot be deleted, only voided
// NOTE: this code won't work, it's coming from my head and note from the actual source, I forget
// what class I'd need to add to the DbEntityValidationResult collection for this type of validation!
if (PaidAmount != 0)
validations.Add(new ValidationResult("A paid SalesOrder cannot be deleted, only voided"));
return validations;
}
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> validations = new List<ValidationResult>();
// Verify that the exempt reason is filled in if the sales tax flag is blank
if (!IsTaxable && string.IsNullOrEmpty(TaxExemptReason))
validations.Add(new ValidationResult("The Tax Exempt Reason cannot be blank for non-taxable orders"));
return validations;
}
....
}
私は正しい方向に進んでいますか?もっと良い方法はありますか?
ありがとう、
CList
編集---Pawelによって提案された1インターフェース方式の要約(下記)
以下に示す1つのインターフェースの方法と、上記の私の方法は、あなたがそれをどのようにやりたいかという点で、チョコレート対バニラの議論のほんの少しだと思います。多数の更新/削除のパフォーマンスはほぼ同じである必要があります。削除の検証を、検証済みのすべてのクラスに適用されない別個のインターフェイスにしたい場合がありますが、すべての検証を1か所にまとめたい場合はここにあります...
DBContextを変更します
protected override bool ShouldValidateEntity(DbEntityEntry entityEntry)
{
return entityEntry.Sate == EntityState.Deleted ||
base.ShouldValidateEntity(entityEntry);
}
protected override DbEntityValidationResult ValidateEntity(DbEntityEntry entityEntry, IDictionary<object, object> items)
{
var myItems = new Dictionary<object, object>();
myItems.Add("IsDelete", (entityEntry.State == EntityState.Deleted));
// You could also pass the whole context to the validation routines if you need to, which might be helpful if the
// validations need to do additional lookups on other DbSets
// myItems.Add("Context", this);
return base.ValidateEntity(entityEntry, myItems);
}
エンティティの検証に削除検証を入れます
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> validations = new List<ValidationResult>();
bool isDelete = validationContext.Items.ContainsKey("IsDelete")
? (bool)validationContext.Items["IsDelete"]
: false;
if (isDelete)
{
if (PaidAmount != 0)
validations.Add(new ValidationResult("You cannot delete a paid Sales Order Line", new string[] { "PaidAmount" }));
return validations;
}
// Update / Add validations!!
// Verify that the exempt reason is filled in if the sales tax flag is blank
if (!IsTaxable && string.IsNullOrEmpty(TaxExemptReason))
validations.Add(new ValidationResult("The Tax Exempt Reason cannot be blank for non-taxable orders"));
return validations;
}
...簡潔にするために、すべてのcheck-if-deleteコードを1つの場所に配置するだけで、ValidationContextクラスに拡張メソッドを作成することもできます(そのようなことに興味がある場合)。 ..
public static class MyExtensions
{
public static bool IsDelete(this System.ComponentModel.DataAnnotations.ValidationContext validationContext)
{
return validationContext.Items.ContainsKey("IsDelete")
? (bool)validationContext.Items["IsDelete"]
: false;
}
}
...これにより、検証コードにこれが提供されます...
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
List<ValidationResult> validations = new List<ValidationResult>();
if (validationContext.IsDelete())
{
....