0

MVC n 層アプリケーション用の Entity Framework (EF) を使い始めました。これが Web アプリケーション (ステートレス) であることは明らかであるように思われますが、分離オブジェクト モデルを使用する必要があります。追加操作を行うことにあいまいさはありません。ただし、編集を行う場合は、2 つの方法があります。

  1. 元のオブジェクトをコンテキストで取得し、更新されたオブジェクトをアタッチしてからデータベースに保存します。この質問への回答で述べたようなもの EF4 Context.ApplyCurrentValues は現在の値を更新しません
  2. この記事http://msdn.microsoft.com/en-us/data/jj592677.aspxで説明されているように、オブジェクトの個々のフィールドの IsModified プロパティを使用して、個々の変更されたプロパティを明示的に設定します 。

方法 1 には、更新の実行が必要になるたびにオブジェクトをデータベースからメモリにロードする必要があるという欠点があります。方法 2 では、オブジェクトが更新される場所から IsModified として設定するフィールドを手動で true に渡す必要があります。たとえば、オブジェクトごとに、オブジェクトのフィールドごとにブール コレクション オブジェクトを作成する必要がある場合があります。例えば

SaveEntity(EntityClass e, EntityStateClass ec)
{
  context.Entry(e).Property("Name").IsModified = ec.NameState;

  context.SaveChanges();
}

class EntityStateClass{ public bool NameState;} 

私は単純にパフォーマンスのために方法 2 を好みますが、使用している n 層アーキテクチャとリポジトリ パターンによって妨げられています。My Repository インターフェイスは、任意のオブジェクトの保存方法を制限します。

 SaveEntity(EntityClass e);

したがって、「状態」オブジェクトを渡すことはできません。コンテキスト クラスは利用できず、DAL の外部では利用できません。したがって、プロパティを外部に設定することはできません。これを達成するための「適切な」方法はありますか?
注: HTML を軽量に保つことを意図しているため、状態を持つエンティティをクライアント (ブラウザー) に送信できないため、自己追跡エンティティも問題外です。

編集:多くのことを考えた後、次のメカニズムを使用して、ドメインクラスの各フィールドの変更された状態を追跡しようとしています

  • エンティティ クラスの部分クラスを宣言します。
  • 更新可能なフィールドごとに、"IsModified_ FieldName "のようなブール プロパティを宣言します。
  • フィールドが設定されている場合は、「IsModified_ FieldName」プロパティを設定します。

ただし、これには、Entity Framework が自動生成する暗黙的なプロパティではなく、明示的なプロパティを生成する必要があります。EF はこれを行うためのハンドルを提供しますか?

ここに私が達成しようとしているもののサンプルコードがあります

 //Save Method for class EntityClass. 
 SaveEntity(EntityClass e)
 {
   context.Entry(e).Property("Name").IsModified = e.IsModified_Name;
   context.SaveChanges();
 }

//EntityClass is class autogenerated by EF
 public partial class EntityClass
  {

        //This is auto-generated property by EF
        public string Name {get; set;}

        /* This is what I would like EF to do
            private string name;
            public string Name 
            {
               get {return Name;}
               set {
                     name = value;
                     //this is what I would like to do
                     this.IsModified_Name = true;
                   };

            }
         */
 }

 //This is another partial definition for EntityClass that I will provide
  public partial class EntityClass
  {
     //This property will be set to true if "Name" is set
      public bool IsModified_Name {get; set;}
  }

PS: 私が提供した情報が不十分なようで、回答がありません。

  • DbContext (データベースファーストモデル) を使用しています
  • EF はクラス ファイルを自動生成します。したがって、データベースを更新するたびに、クラス ファイルが再生成されます。
4

1 に答える 1

1

具体的な質問に対して: エンティティは T4 テンプレートによって生成され、このテンプレート (テキスト形式) を変更して、希望する方法でエンティティを生成できるはずです。

しかし、私はあなたのコンセプトについていくつかのコメントがあります:

  • Web アプリケーションでは、データは通常、ブラウザーでユーザーによって変更されます。実際に何が変更されたのかを明確に知るには、ブラウザーの変更を追跡する必要があります (おそらく、ユーザーがテキスト ボックスを編集するときに、データ (ViewModel など) にフラグを設定する Javascript によって)。

    ブラウザで変更を追跡しないとどうなりますか? データはサーバーに戻され、サーバー側 (コントローラー内の MVC を使用) ではどのプロパティが変更されたかわかりません。したがって、唯一のチャンスは、投稿されたすべてのプロパティをマップして戻すことであり、ユーザーが実際に変更を行ったかどうかに関係なく、EntityClassすべてのプロパティが としてマークされます。後でEF をModified呼び出すと、これらすべてのプロパティを含むステートメントが作成され、回避したい不要なオーバーヘッドが生じます。SaveChangesUPDATE

  • エンティティ全体の状態Modifiedを どちらの場合も、すべてのプロパティを としてマークしましModifiedた。例外は、エンティティの部分的な変更です。たとえば、 andプロパティと、プロパティのみを含む対応する ViewModelを編集することはできますが編集できないビューをCustomer持つエンティティがあります。この場合、プロシージャはエンティティのプロパティをとしてマークするだけで、. プロパティ値をデータベースに保存しないため、ここで少し節約できます。ただし、変更されていなくても保存します。NameCityNameCityNameNameCustomerModifiedCityCityName

  • ソリューション 1 ( ) を使用する場合、最初にデータベースからエンティティをロードする必要がありますが、データベース内の値と比較して実際に変更されApplyCurrentValuesたプロパティのみをマークします。Modifiedユーザーが何も変更しなかった場合、noUPDATEはまったく書き込まれません。

  • コンセプトを実装するのはまだ始まったばかりだということを心に留めておいてください。スカラー プロパティの変更、つまりリレーションシップの変更以外にも、ブラウザーで発生する可能性のあるデータの変更があります。たとえば、ユーザーがリレーションシップを から に変更しOrderたり、と のコレクションをCustomer持つビューがあり、ユーザーはヘッダーを編集できるだけでなく、 を編集したり、新しい を削除および追加したりできます。データがブラウザーからサーバーに戻ってきたときに、どのコレクション項目が追加され、どのコレクション項目が削除されたかをどのように認識したいですか?実際のデータまたはOrderOrderItemsOrderOrderItemOrderItemOrderOrderItemをデータベースから取得し、変更をデータベースの元のエンティティにマージしますか?

個人的には、次の理由からオプション 1 に投票します。

  • 追加の追跡情報を持たない実際の POCO を使用できます。(ところで、EF 変更追跡プロキシがすぐに提供する独自の追跡を実装することによって車輪を再発明していないかどうか、私には疑問があります。)

  • 非常に複雑になる可能性があり、非表示のフォーム フィールドなどに変更フラグを書き込むために、すべての編集ビューで Javascript が必要になるブラウザでの変更を追跡する必要はありません。

  • 独自の追跡を実装しなくても、EF の標準機能を使用できます。

  • エンティティを更新する場合は、データベースからエンティティをロードする必要があります。これは本当です。しかし、これは、データがワイヤを介して前後に実行されなければならない Web アプリケーションの実際のパフォーマンスのボトルネックでしょうか (また、リフレクション (高速であるとはあまり知られていません) がモデル バインダーに関係しています)。データベースが Web サーバーから離れていて、9600 ボーのモデムで接続されているかどうかについては何も言いません。しかしそうでなければ、あなたの計画は時期尚早の最適化であるだけでなく、時期尚早のアーキテクチャのようなものです。実際に存在するかどうかわからないパフォーマンスの問題を解決するために、「遅くなる可能性がある」に基づいて潜在的に複雑なアーキテクチャを構築し始めています。

于 2013-02-02T14:35:23.730 に答える