簡體   English   中英

懶惰和渴望加載MVC 5

[英]Lazy & eager Loading MVC 5

我有以下代碼,我嘗試讓所有學生(UserTypeID = 2)

using SchoolData;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace SchoolAPI.Controllers
{
    public class StudentsController : ApiController
    {
        public List<User> Get()
        {
            using(SchoolEntities DB = new SchoolEntities())
            {
                var L = DB.Users.Where(u => u.UserTypeID == 2).ToList();
                return L;
            }
        }

    public User Get(int id)
    {
        using(SchoolEntities DB = new SchoolEntities())
        {
            return DB.Users.Where(u => u.UserTypeID == 2).FirstOrDefault(u => u.UID == id);
        }
    }
}
}

當我在啟用延遲加載的情況下運行此代碼時,我嘗試通過功能Get()吸引所有學生,這將引發錯誤:

"Message": "An error has occurred.",
    "ExceptionMessage": "The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; charset=utf-8'.",
    "ExceptionType": "System.InvalidOperationException",
    "StackTrace": null,
    "InnerException": {
        "Message": "An error has occurred.",
        "ExceptionMessage": "Error getting value from 'City' on 'System.Data.Entity.DynamicProxies.User_43D4A249734A75DBA5AC314F4FE462E834BDC252CC9384BF940FE65C74CE3D08'

"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

當我嘗試禁用惰性模式並重新運行時,它會正確獲取對象,但帶有一些其他不需要的參數,如下所示:

{
    "City": null,
    "CourseDetails": [],
    "StudentsCourses": [],
    "UserType": null,
    "UID": 2,
    "FName": "Ahmed",
    "LName": "Mano",
    "Birthdate": "1995-05-27T00:00:00",
    "CityID": 1,
    "UserTypeID": 2
}

而且我既不需要CourseDetails,StudentsCourses,City或UserType

當對象序列化為json時,無論是否在客戶端上使用它們,這些屬性都會被序列化。 由於序列化是在您退出using塊之后發生的,因此在處理上下文之后可以訪問屬性。 您可以做以下三件事之一:

  1. 使用[JsonIgnore]屬性標記未使用的屬性。 詳情請看這里

  2. 創建僅包含客戶端中所需屬性的第二個類,然后使用SelectUser投影到該新的更特定的對象。 或使用auromapper自動進行映射。 關於auromapper, 可能是一篇入門的好文章

  3. 為每個控制器創建一個上下文,在承包商中對其進行初始化,然后僅以對控制器dispose方法的替代方式對其進行處理。 這將確保上下文在序列化期間可用。

從性能的角度來看,2是最好的選擇,因為您只發送所需的信息,並且可以靈活地將輸出調整為每個操作(也許其他操作需要這些字段)。 3是最簡單的實現,但是您將發送大量不需要的數據,並不必要地訪問數據庫。 1提供並且易於修復,直到其他人向模型添加新屬性,而且,您最終可能會在客戶端中得到不僅不需要的數據,而且這些數據不應到達客戶端(密碼,其他敏感信息)可能會添加到模型中)

Titian Cernicova完全正確,我只想添加一件事:如果您從WebAPI控制器返回了一個Entity Object,您可能會遇到內存問題,並且可能在服務器上發生內存泄漏, 請不要這樣做

因此,一個好的做法是創建一個具有所需屬性的數據傳輸對象,例如:

public class DtoUser
{
    public int UID { get; set; }
    public string FName { get; set; }
    public DateTime Birthdate { get; set; }
    public int CityID { get; set; }
    public int UserTypeID { get; set; }
}

將您的實體對象轉換為此對象並返回。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM