2013-03-21 43 views
9

Tôi đã nhận thấy hành vi sau và tôi tự hỏi liệu có ai có thể giải thích lý do tại sao nó xảy ra và cách nó có thể được ngăn chặn.ASP.NET MVC đọc thuộc tính khi đối tượng được tạo

Trong các lớp học một phần của mình, tôi đã thêm các thuộc tính chỉ đọc khác nhau không có trong cơ sở dữ liệu. Khi đối tượng được tạo, các thuộc tính này được truy cập trước khi chúng ta tới phương thức Create của controller. Tuy nhiên, các thuộc tính được khai báo chỉ với get; set; không được truy cập.

Để xây dựng, sử dụng ví dụ rất đơn giản, nếu tôi có các thuộc tính sau:

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

Nếu tôi sau đó đặt breakpoint trên các thuộc tính, khi đối tượng được tạo ra breakpoint là hit cho các tài sản đầu tiên nhưng không thư hai. Tuy nhiên, nếu tôi có phương thức:

public bool getBoolProperty() { 
    return true; 
} 

thì điều này không được truy cập.

Tôi đã thử tất cả các loại biến thể và chú thích

// 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; 
    } 
} 

Tôi đã thử khai báo các thuộc tính virtual, tuy nhiên tất cả các biến, ngoại trừ get; set; đa dạng, được truy cập khi đối tượng được tạo ra. Hành vi này cũng xảy ra đối với tài sản số nguyên

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

và tài sản ngày/giờ,

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

nhưng không phải cho các thuộc tính chuỗi

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

hoặc tổ chức khác thuộc tính

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

Các probl em là tôi có một số các đặc tính này có thể liên quan đến một số logic mà có thể cần truy cập cơ sở dữ liệu ví dụ

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

đó, tại thời điểm tạo ra, đơn vị sẽ không có. Rõ ràng là tôi có thể giải quyết vấn đề này bằng cách làm mọi thứ thành một phương pháp, nhưng tôi muốn biết tại sao ASP.NET MVC truy cập các thuộc tính này trên tạo đối tượng (Một số loại xác nhận nội bộ), và tôi muốn biết nếu có bất kỳ phương pháp nào ngăn chặn điều này, có thể bằng cách chú thích mà tôi không gặp phải.

dự án của tôi là cơ sở dữ liệu đầu tiên, C#, EF 4.1, MVC

Sửa

Tôi cũng nên chỉ ra tôi đang sử dụng các đối tượng POCO và truy cập vào cơ sở dữ liệu thông qua các thủ tục lưu trữ/chức năng nhập khẩu.

Một ý nghĩ xảy ra với tôi là các thuộc tính này đang được truy cập như một phần của hệ thống theo dõi thay đổi như được thảo luận here. Có vẻ như những gì có thể xảy ra là một ảnh chụp đang được chụp của mục mới được tạo ra. Tôi đã cố gắng tắt tạo proxy

dbContext.ContextOptions.ProxyCreationEnabled = false; 

nhưng các thuộc tính vẫn đang được truy cập khi tạo. đề nghị

Sửa 20130322

Sau @ ladislavmrnka của khám phá stack trace Tôi nhận điều này:

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) 

Trong đó bạn sẽ nhận thấy các cuộc gọi đến một hoặc hai validator. Khi thử nghiệm, tôi đã thay đổi thuộc tính bool thành thuộc tính bool rỗng:

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

Lần này thuộc tính không được truy cập khi đối tượng được tạo. Đây là hành vi mong muốn của tôi, tuy nhiên, tôi không muốn phải thay đổi tất cả các thuộc tính tùy chỉnh của mình thành rỗng, do đó, câu hỏi của tôi bây giờ trở thành ...

Có cách nào để yêu cầu khung không xác thực bất động sản? Có lẽ thông qua một thuộc tính. This answer gần như trả lời câu hỏi, nhưng vì tôi đang sử dụng cơ sở dữ liệu đầu tiên, tôi dường như không có thuộc tính ValidateOnSaveEnabled để tắt. Có lẽ tôi cần phải xem lại các mô hình của tôi.

+0

Truy cập các thuộc tính có thể là một số điều bản đồ hoặc phản chiếu. Nhưng dù sao, bạn nên chú thích các thuộc tính với [NotMapped]. –

+0

Vậy trình gỡ lỗi không chỉ dừng lại khi bạn sử dụng thuộc tính tự động? Trình gỡ lỗi không dừng lại trên các thuộc tính được tự động triển khai trừ khi bạn sử dụng [trick] (http://stackoverflow.com/questions/4408110/debugging-automatic-properties). Đối với các thuộc tính khác bắt đầu bằng cách khám phá ngăn xếp cuộc gọi để tìm hiểu nguyên nhân truy cập. –

+0

@LadislavMrnka, tôi đang sử dụng Web Developer Express không có cửa sổ điểm ngắt. Mẹo hay trên ngăn xếp cuộc gọi mặc dù – Webbie4

Trả lời

1

Giống như hầu hết các vấn đề của EF, câu trả lời nằm ở mô hình xem. Vì hầu hết các thuộc tính đã được truy cập không có liên quan cho đến khi mô hình đã được tạo và duy trì cho db, tôi đã tạo một mô hình khung nhìn đặc biệt cho chế độ xem Tạo chỉ chứa số lượng thuộc tính tối thiểu tuyệt đối cần thiết để tạo ngươi mâu. Tôi đã sửa đổi phương thức Create của bộ điều khiển để chấp nhận mô hình khung nhìn mới của tôi và thì đấy, khi tạo mô hình mới này, không có quyền truy cập vào bất kỳ thuộc tính không liên quan nào trên mô hình chính. Vì vậy, câu trả lời cho câu hỏi ban đầu của tôi dường như là khuôn khổ thực thể thực hiện xác nhận trên tất cả các thuộc tính vô hướng không nullable khi một đối tượng được tạo ra và một cách để tránh điều này như được giải thích ở trên.

+0

Đây thực sự là điểm MVC chứ không phải điểm EF. MVC chạy ModelBinder và là một phần của nó, nó chạy Validation Logic. Đó là logic xác thực của MVC cố gắng đọc thuộc tính. Điểm của bạn ở đây là chính xác mặc dù, Bạn nên luôn sử dụng ViewModels cho chế độ xem MVC và không bao giờ liên kết trực tiếp với Thực thể của mình (xem mô hình cũng không được chứa thực thể trong đó) Ngoài ra, để đảm bảo bộ sưu tập của bạn không rỗng trong thực thể, bạn có thể khởi tạo chúng dưới dạng hashsets trong constructor của bạn. Điều này đảm bảo giúp các mô hình EF của bạn hoạt động trong một bối cảnh tách rời. – stevenrcfox

Các vấn đề liên quan