13

AssociationChanged イベントがあることは承知していますが、このイベントは関連付けが行われた後に発生します。AssociationChanging イベントはありません。では、何らかの検証の理由で例外をスローしたい場合、どうすれば元の値に戻せますか?

また、他のエンティティからの情報に基づいて自分のエンティティのデフォルト値を設定したいのですが、データベースに挿入するためにエンティティがインスタンス化されていることがわかっている場合にのみこれを行います。それと、既存のデータに基づいて入力されようとしているためにインスタンス化されるオブジェクトとの違いをどのように見分けることができますか? 私は知っているはずですか?それは、エンティティのビジネス ロジックの外にある必要がある、考慮されたビジネス ロジックですか?

その場合、これらすべてのエンティティをラップするコントローラー クラスを設計する必要がありますか? 私の懸念は、エンティティを返送する場合、クライアントにプロパティへのアクセスを許可したいが、プロパティの設定方法、デフォルト設定などの検証を厳密に制御したいということです。私が見たすべての例は、コンテキストを参照しています。私のエンティティ部分クラスの検証の範囲外ですよね?

ところで、私はEFPocoAdapterを見ましたが、私の人生では、POCOクラス内からリストを作成する方法を決定できません...EFPocoクラスからコンテキストに到達する方法を知っている人はいますか?

4

5 に答える 5

2

これは私が残したコメントへの返信です。うまくいけば、これはあなたの質問に答えます、シミー。コメントするだけで、質問に答えられない場合は短縮または削除します。

INotifyPropertyChangingインターフェイスとINotifyPropertyChangedインターフェイスの両方をクラスに実装する必要があります(これらを内部的に実装すると思われるエンティティフレームワークオブジェクトのようなものでない限り)。

また、このプロパティに値を設定する前に、PropertyChangingEventArgsコンストラクターでプロパティの名前を使用して、NotifyPropertyChanging.PropertyChangingイベントを発生させる必要があります。

そして、この値を設定した後、NofityPropertyChanged.PropertyChangedイベントを発生させる必要があります。これも、PropertyChangedEventArgsコンストラクターで発生しているプロパティの名前を使用します。

次に、PropertyChangingイベントとPropertyChangedイベントを処理する必要があります。PropertyChangingイベントでは、値をキャッシュする必要があります。PropertyChangedイベントでは、例外を比較してスローできます。

PropertyChanging / PropertyChangedイベント引数からプロパティを取得するには、relfectionを使用する必要があります。

// PropertyName is the key, and the PropertyValue is the value.
Dictionary <string, object> propertyDict = new Dictionary<object, object>();

    // Convert this function prototype to C# from VBNet.  I like how Handles is descriptive.
    Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
    {
      if (sender == null || preventRecursion)
      {
        return;
      } // End if

      Type senderType = sender.GetType();
      PropertyInfo info = senderType.GetProperty(e.PropertyName);
      object propertyValue = info.GetValue(sender, null);

      // Change this so it checks if e.PropertyName already exists.
      propertyDict.Add(e.PropertyName, propertyValue);
    } // End PropertyChanging() Event

     // Convert this function prototype to C# from VBNet.  I like how Handles is descriptive.
    Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
    {
      if (sender == null || preventRecursion)
      {
        return;
      } // End if

      Type senderType = sender.GetType();
      PropertyInfo info = senderType.GetProperty(e.PropertyName);
      object propertyValue = info.GetValue(sender, null);

      // Change this so it makes sure e.PropertyName exists.
      object oldValue = propertyDict(e.PropertyName);
      object newValue = propertyValue;

      // No longer needed.
      propertyDict.Remove(e.PropertyName);

      if (/* some condition */)
      {
        try {
          preventRecursion = true;
          info.SetValue(oldValue, null);
          Throw New Exception();
        } finally {
          preventRecursion = false;
        } // End try
      } // End if
    } // End PropertyChanging() Event

これらのメソッドの上に追加するのを忘れたブール値であるPreventRecursionをどのように使用しているかに注意してください。プロパティを以前の値にリセットすると、これらのイベントが呼び出されます。

tl; dr

これで、INotifyPropertyChangedから継承する単一のイベントを派生させることができますが、前の値とプロパティ名を表すオブジェクトを保持する引数を使用します。これにより、発生するイベントの数が1つに減り、同様の機能があり、INotifyPropertyChangedとの下位互換性があります。

ただし、プロパティが設定される前に何かを処理したい場合(たとえば、プロパティが元に戻せない変更を行う場合、またはその変数を設定する前に他のプロパティを設定する必要がある場合、そうでない場合は例外がスローされます)、それを行うことはできません。

全体として、この方法は非常に古い方法です。私はポーカービリアンの答えを受け取り、無効なデータを入力することができます。ただし、データベースへの保存は許可しないでください。

Entity Frameworkには、検証に向けた優れたコードがいくつかあります。属性を介してプロパティに検証を追加します。そして、それらの属性を処理する作業を処理します。次に、EntityFramework固有の検証を呼び出すIsValidというプロパティを作成できます。また、フィールドエラー(間違った文字の入力や文字列の長すぎるなど)とクラスエラー(データの欠落やキーの競合など)の両方を区別します。

次に、IsValidをコントロールの検証にバインドすると、無効なデータが入力されている間、コントロールに赤いバブルが表示されます。または、IsValid検証を自分で実装することもできます。ただし、IsValidがfalseの場合、SaveChangesイベントは保存をキャンセルする必要があります。

ところで。提供されたコードはコンパイルされず、疑似コードのみです(vbとc#を混合)。しかし、c#だけの場合よりもはるかにわかりやすく、処理されている内容を正確に示していると思います。

于 2010-12-23T19:11:45.390 に答える
0

CancelEventArgsAssociationChanging(から継承する)イベントがないことは深刻な欠如です。

それもとても気になりますので、これをマイクロソフトコネクトに報告しました。ここに投票してください!

ところで、これはPropertyChangingEventArgsがCancelEventArgsを継承しないことも愚かだと思います。例外を付けてキャンセルすることは必ずしも洗練された解決策ではないためです。さらに、例外をスローすると、OnPropertyChangingEventを呼び出して、返されたe.Cancelを確認するよりもパフォーマンスが高くなります。 、とにかく両方と呼ぶPropertyChangingEventを発生させるよりもコストがかかりません。
また、例外の方法を主張する人のために、e.Cancelをtrueとしてマークする代わりに、とにかくハンドラーで例外をスローすることができます。ここに投票してください。

于 2010-08-11T23:19:14.210 に答える
0

質問の一部に回答したり、ADB の回答を説明したりするには、ObjectStateManager.GetObjectStateEntry を使用してエンティティの状態を見つけ、カスタムのデフォルト ロジックを記述します。

SaveChanges は、使用できるコンテキストのメソッドです。または、SavingChanges は、SaveChanges が呼び出される前に発生するイベントです。

変更を中止したくない場合は、SaveChanges をオーバーライドして base.SaveChanges のみを呼び出すことができます。

コンテキストの ObjectMaterialized イベントもあります。

2 つの間で、すべての検証および作成コードを 1 つの場所に貼り付けることができます。これは、それらが複雑で、他のオブジェクトの値が含まれている場合などに適している場合があります。

于 2010-11-08T15:21:16.440 に答える
0

最初の質問に関しては、ビジネス ロジックとしてアソシエーションへの変更を実装するだけです。たとえば、複数の生徒を持つ教師クラスを追加する場合、次のように生徒を追加しないでください。

aTeacher.Students.Add(new Student)

代わりに、AddStudent メソッドを作成します

public Student AddNewStudent(string name, string studentID)
{

    Student s = new Student( name, studentID);
    s.Teacher = this; // changes the association
    return s;
}

そうすれば、関連付けがいつ変更されるかを完全に制御できます。もちろん、別のプログラマーが学生を直接追加するのを妨げているのは何ですか? Student 側では、Teacher セッターをプライベートに設定できます (また、コンストラクターを変更して、教師などを受け入れるようにします)。教師側で、Students コレクションを挿入不可にするにはどうすればよいですか? 確かではありません...挿入を受け入れないカスタムコレクションに変換するかもしれません。

質問の 2 番目の部分については、おそらく OnVarNameChanging イベントを使用できます。EntityState が「New」の場合、実際の値を取得するロジックを適用できます。

変更を保存するときに発生するイベント (OnSavingChanges?) もあります。これを使用して、新しいオブジェクトを特定し、いくつかの値を設定できます。

しかし、おそらく最も簡単な解決策は、コンストラクターで常にデフォルトを設定することであり、データが DB からロードされると上書きされます。

幸運を

于 2009-08-19T17:36:20.483 に答える
0

次のように、必要に応じてインスタンスを生成するファクトリを作成します。

getStudent(String studentName, long studentId, Teacher teacher) {
    return new Student(studentName, studentId);
}

getStudentForDBInseration(String studentName, long studentId, Teacher teacher) {
    Student student = getStudent(studentName, studentId);
    student = teacher;
    //some entity frameworks need the student to be in the teachers student list
    //so you might need to add the student to the teachers student list
    teacher.addStudent(student);
}
于 2009-09-23T21:46:10.083 に答える