2016-10-21 15 views
2

現在、C#Entity Frameworkでカスタム制約を作成しようとしています。より詳細に:C#Entity Frameworkカスタム制約

私は特定の値(たとえば1,2,3)しか持てない数値フィールドを持っています。どのようにコードの最初の環境でこの制約を達成するのですか?

+2

すべてのEntity Frameworkタグは何ですか? –

+0

申し訳ありませんが重複したものを削除しました –

答えて

2

エンティティフレームワークが自動的にValidationAttribute sがモデルに追加した検証を検証します。 RequiredAttributeまたはRangeAttributeは、この属性の組み込みサブクラスの2つの例です。

カスタム検証をしたい場合は、最も便利な方法は、このメカニズムをピギーバックして、独自のValidationAttributeサブクラスを作成することです。

あなたは、このような場合のために、あなたはRangeAttributeを使用することはできませんが、あなたは自分の属性を作ることができる値の非連続的な範囲を確認したい場合:

public class AllowedValuesAttribute : ValidationAttribute 
{ 
    private readonly ICollection<object> _validValues; 
    private readonly Type _type; 

    public AllowedValuesAttribute(Type type, object[] validValues) 
    { 
     _type = type; 
     _validValues = validValues.Where(v => v != null && v.GetType() == type).ToList(); 
    } 

    public override bool IsValid(object value) 
    { 
     return value.GetType() == _type && _validValues.Contains(value); 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     return string.Format("Value for '{0}' is not an allowed value", name); 
    } 
} 

使用法:

[AllowedValues(typeof(int), new object[] { 1, 2, 4, 8, 16 })] 
public int Base { get; set; } 

ここでは固定値を使用する必要があることに注意してください。属性の内容はコンパイル時に知っていなければならないからです。また、(現在)C#は汎用属性をサポートしていないため、objectを使用する必要があります。それ以外にも、さまざまなオプションがあります。たとえば、属性には実行時に許可された値を、おそらく名前付きソースから検索するメソッドがあるため、コンストラクタでこの名前を指定できます。

検証属性を使用してエンティティクラスを飾ることに問題はありません。エンティティモデルはで、ドメインモデルではなく、データアクセスレイヤの一部です。主な目的は、アプリケーションのデータアクセスを容易にすることです(そして、そうすべきです)。エンティティモデルがビジネスロジックをサポートする場合もありますが、単なるボーナスになります。

+0

それについて考えた後、私はまだなぜs.o.これを使用します。これに対する属性は単純な間違った方法です。あなたの例はそれを示しています:ここでは、値が例えば 'Enum'か単純な' Enum'であれば 'Flag'-' Enn'です。 '1,3,7,20、...'データに特定の意味がある場合は、テーブルを作成し、PKをFKとして使用します。他のコントローラが他のintを入力する可能性があるので、実際にintを使用する必要があるのであれば、コントローラでそれを扱うか、viewmodelで注釈を使用します(そうでなければ、enumまたはFK it)。申し訳ありませんが、エンティティクラスで使用する理由はまだありません。 –

+0

@MatthiasBurgerアプリケーションでは、*単一点検証*をしたいと考えています。私は例外をスローするプロパティセッターを決して使用しません。これにより、例外を処理する必要がある多くの潜在的なコード場所が導入されます。 EFの検証が始まると、プロパティは検証されません。アトリビュートの利点は、適切なタイミングで正しい方法で、つまり他のEF検証と同様に検証することです。違反は他の検証エラーの中にうまく列挙されます。あなたは無料で多くを得る。 –

+0

@MatthiasBurgerもちろん、FKチェックには使用しません。はい、enumをお勧めします。比較的単純なケースでは、属性で十分です。 –

0

D.Macが書いたように、ドメインモデルにデータアノテーションを追加することは非常に悪い習慣です。 それでよかったのですか?

あなたがあなたの財産のセッター

でやりたいとあなたはいつものJavaScript/HTMLを変更することができますので、唯一のフロントエンドでそれを制限することは、最善の解決策ではありませんでした

public MyClass 
{  
    private int myNumberField; 
    public int MyNumberField 
    { 
     get { return myNumberField; } 
     set 
     { 
      if (value >= 1 && value <=3) 
       myNumberField = value; 
      else 
       // throw exception? 
       // set default-value (maybe 1)? 
       // do nothing? 
     } 
    } 

} 

- しかし、あなたがすべき1、2、または3の値しか挿入できないことをユーザーに示します。 データアノテーションを含むビューモデルでも制限します。

OR:あなたもEntityFrameworks SaveChangesをオーバーライドして、あなたのビジネスロジックを追加することができ

public override int SaveChanges(SaveOptions options) 
{ 

    foreach (ObjectStateEntry entry in 
     ObjectStateManager.GetObjectStateEntries(
     EntityState.Added | EntityState.Modified)) 
    { 
     // Validate the objects in the Added and Modified state 
     // if the validation fails, e.g. throw an exeption. 
    } 
    return base.SaveChanges(options); 
} 
関連する問題