2013-03-21 5 views
9

Я заметил следующее поведение, и мне интересно, может ли кто-нибудь объяснить, почему это происходит и как его можно предотвратить.ASP.NET MVC считывает свойства при создании объекта

В моих частных классах я добавил различные свойства только для чтения, которых нет в базе данных. Когда объект создается, эти свойства доступны, прежде чем мы перейдем к методу Create контроллера. Однако свойства, объявленные только с get; set;, не доступны.

Разрабатывать, используя самые простые примеры, если у меня есть следующие свойства:

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

Если бы я тогда поставил точки останова на свойства, когда объект создается точка останова для первого свойства, но не второй. Однако, если у меня есть метод:

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(); 
    } 
} 

Th е У меня проблема в том, что некоторые из этих свойств может включать в себя некоторую логику, которая может понадобиться доступ к базе данных, например,

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

, который, в момент создания, компания не будет иметь.

Очевидно, что я могу обойти это, сделав все методом, но мне было бы интересно узнать, почему ASP.NET MVC обращается к этим свойствам при создании объекта (возможно, какая-то внутренняя проверка), и мне было бы интересно узнать если есть какие-либо способы предотвращения этого, возможно, путем аннотации, с которой я не сталкивался.

Мой проект базы данных первых, C#, EF 4,1, MVC

Редактировать

Я хотел бы также отметить, я использую POCO объектов и доступа к базе данных с помощью хранимых процедур/импорта функций.

Одна мысль пришла мне в голову, что эти свойства доступны как часть системы отслеживания изменений, как обсуждалось here. Кажется, что, вероятно, происходит моментальный снимок вновь созданного элемента. Я попытался отключив создание прокси

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) 

В нем вы увидите вызовы валидатора или два. В качестве теста я изменил свое свойство Его к обнуляемому BOOL собственности:

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

На этот раз свойство не доступно, когда был создан объект. Это мое желаемое поведение, однако, я не хочу, чтобы все мои пользовательские свойства были обнуляемы, поэтому мой вопрос теперь становится ...

Есть ли способ сообщить структуре не проверять имущество? Возможно через атрибут. This answer почти отвечает на вопрос, но поскольку я сначала использую базу данных, у меня, похоже, нет свойства ValidateOnSaveEnabled для отключения. Возможно, мне нужно вернуться к моим моделям.

+0

Доступ к свойствам, вероятно, является некоторой картиной или отражением. Во всяком случае, вы должны аннотировать свойства с помощью [NotMapped]. –

+0

Итак, отладчик не останавливается, только когда вы используете свойство auto? Отладчик не останавливается на автоматически реализованных свойствах, если вы не используете [трюк] (http://stackoverflow.com/questions/4408110/debugging-automatic-properties). Для других свойств начинайте с изучения стека вызовов, чтобы узнать, что вызывает доступ. –

+0

@LadislavMrnka, я использую Web Developer Express, к сожалению, у которого нет окна точек останова. Хороший совет в стеке вызовов, хотя – Webbie4

ответ

1

Как и в случае с большинством проблем EF, ответ лежит на моделях просмотра.

Поскольку большинство свойств, к которым обращаются, не были актуальны до тех пор, пока модель не была создана и не была сохранена в db, я создал модель представления, особенно для представления Create, которая содержала только абсолютное минимальное количество свойств, необходимых для создания модель. Я изменил метод Create контроллера, чтобы принять мою новую модель представления и вуаля, при создании этой новой модели не было доступа к каким-либо нерелевантным свойствам основной модели.

Таким образом, ответ на мой первоначальный вопрос заключается в том, что инфраструктура сущности выполняет проверку на все свойства, не связанные с нулевым значением, когда объект создан, и один из способов избежать этого объясняется выше.

+0

Это на самом деле точка MVC, а не точка EF. MVC запускает ModelBinder и, как часть этого, запускает логику проверки. Логика проверки MVC пытается прочитать свойство. Ваша точка зрения правильная, однако, вы всегда должны использовать представления ViewModels для MVC и никогда не привязываться непосредственно к своим объектам (модели просмотра также не должны содержать в них сущности) Кроме того, чтобы гарантировать, что ваши коллекции не являются пустыми для сущностей, вы можете инициализировать их как hashsets в своем конструкторе. Это гарантирует, что ваши модели EF работают в изолированном контексте. – stevenrcfox