[英]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塊之后發生的,因此在處理上下文之后可以訪問屬性。 您可以做以下三件事之一:
使用[JsonIgnore]
屬性標記未使用的屬性。 詳情請看這里
創建僅包含客戶端中所需屬性的第二個類,然后使用Select
將User
投影到該新的更特定的對象。 或使用auromapper自動進行映射。 關於auromapper, 這可能是一篇入門的好文章
為每個控制器創建一個上下文,在承包商中對其進行初始化,然后僅以對控制器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.