繁体   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