9

私は次の動作に気付きました。なぜそれが起こっているのか、どのように防ぐことができるのかを誰かが説明できるのだろうか.

私の部分クラスでは、データベースに存在しないさまざまな読み取り専用プロパティを追加しました。オブジェクトが作成されると、コントローラーの Create メソッドに到達する前に、これらのプロパティにアクセスします。ただし、just で宣言されたプロパティにget; set;はアクセスできません。

次のプロパティがある場合、非常に単純な例を使用して詳しく説明します。

public bool getBoolProperty {
    get {
        return true;
    }
}
public bool getSetBoolProperty {
    get; set; 
}

次に、プロパティにブレークポイントを設定すると、オブジェクトが作成されたときに、最初のプロパティではブレークポイントにヒットしますが、2 番目のプロパティにはヒットしません。ただし、メソッドがある場合:

public bool getBoolProperty() {
    return true;
}

これはアクセスされません。

あらゆる種類のバリエーションと注釈を試しました

// empty set
public bool getBoolProperty {
    get {
        return true;
    }
    set {}
}

// not mapped attribute
[NotMapped]
public bool getBoolProperty {
    get {
        return true;
    }
}

// getting private variable
private bool _boolProperty = true;
public bool getPrivateBoolProperty {
    get {
        return _boolProperty;
    }
}

プロパティを宣言しようとしましたが、オブジェクトが作成されると、さまざまなvirtualバリエーションを除くすべてのバリエーションがアクセスされます。get; set;この動作は、整数プロパティでも発生します

public virtual int getIntProperty {
    get {
        return 1;
    }
}

および日付/時刻のプロパティ、

public virtual DateTime getDateProperty {
    get {
        return DateTime.Now;
    }
}

ただし、文字列プロパティではありません

public string getStringProperty {
    get {
        return "Hello String";
    }
}

または他のエンティティ プロパティ

public Item getItem {
    get {
        return new Item();
    }
}

私が抱えている問題は、これらのプロパティの一部に、データベースへのアクセスが必要なロジックが含まれている可能性があることです。

public bool HasChildren {
    get {
        return this.Children !== null && this.Children.Count > 0;
    }
}

作成時には、エンティティにはありません。

明らかに、すべてをメソッドにすることでこれを回避できますが、ASP.NET MVC がオブジェクトの作成時にこれらのプロパティにアクセスする理由 (おそらく何らかの内部検証) を知りたいと思います。おそらく私が遭遇したことのない注釈を介して、これを防ぐ方法。

私のプロジェクトはデータベース ファースト、C#、EF 4.1、MVC です。

編集

また、私は POCO エンティティを使用しており、ストアド プロシージャ/関数のインポートを介してデータベースにアクセスしていることも指摘しておく必要があります。

ここで説明されているように、これらのプロパティは変更追跡システムの一部としてアクセスされているのではないかと思いました。おそらく、新しく作成されたアイテムのスナップショットが作成されているようです。プロキシの作成をオフにしてみました

dbContext.ContextOptions.ProxyCreationEnabled = false;

ただし、プロパティは作成時に引き続きアクセスされます。

編集 20130322

スタックトレースを調査するという@ladislavmrnkaの提案に従って、私はこれを得ました:

at System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component)
at System.Web.Mvc.AssociatedMetadataProvider.<>c__DisplayClassb.<GetPropertyValueAccessor>b__a()
at System.Web.Mvc.ModelMetadata.get_Model()
at System.Web.Mvc.DataAnnotationsModelValidator.<Validate>d__1.MoveNext()
at System.Web.Mvc.ModelValidator.CompositeModelValidator.<Validate>d__5.MoveNext()
at System.Web.Mvc.DefaultModelBinder.OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext)
at System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model)
at System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
at System.Web.Mvc.DefaultModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
at System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor)
at System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
at System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName)
at System.Web.Mvc.Controller.ExecuteCore()
at System.Web.Mvc.ControllerBase.Execute(RequestContext requestContext)
at System.Web.Mvc.ControllerBase.System.Web.Mvc.IController.Execute(RequestContext requestContext)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass6.<>c__DisplayClassb.<BeginProcessRequest>b__5()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass1.<MakeVoidDelegate>b__0()
at System.Web.Mvc.Async.AsyncResultWrapper.<>c__DisplayClass8`1.<BeginSynchronous>b__7(IAsyncResult _)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.End()
at System.Web.Mvc.MvcHandler.<>c__DisplayClasse.<EndProcessRequest>b__d()
at System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f)
at System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action)
at System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

その中で、1 つまたは 2 つのバリデータへの呼び出しに気付くでしょう。テストとして、bool プロパティを null 許容 bool プロパティに変更しました。

public bool? getBoolProperty {
    get {
        return true;
    }
}

今回は、オブジェクトの作成時にプロパティにアクセスしませんでした。これは私の望ましい動作ですが、すべてのカスタム プロパティを null 可能に変更する必要はありません。そのため、私の質問は次のようになります...

プロパティを検証しないようにフレームワークに指示する方法はありますか? おそらく属性を介して。 この回答ValidateOnSaveEnabledはほとんど質問に答えていますが、最初にデータベースを使用しているため、オフにするプロパティがないようです。おそらく、モデルを再検討する必要があります。

4

1 に答える 1

1

ほとんどの EF の問題と同様に、その答えはビュー モデルにあります。

アクセスされたプロパティのほとんどは、モデルが作成されてデータベースに永続化されるまで関連性がなかったので、モデルを作成するために必要な絶対最小数のプロパティのみを含む Create ビュー専用のビュー モデルを作成しました。コントローラーの Create メソッドを変更して、新しいビュー モデルを受け入れるようにしました。この新しいモデルを作成すると、メイン モデルの無関係なプロパティへのアクセスはありませんでした。

したがって、私の元の質問に対する答えは、エンティティ フレームワークが、オブジェクトの作成時にすべての null 非許容スカラー プロパティに対して検証を実行することであり、これを回避する 1 つの方法は上記で説明したとおりです。

于 2013-03-22T11:46:56.660 に答える