懒惰&渴望加载MVC 5

时间:2018-01-22 13:28:53

标签: c# entity-framework asp.net-mvc-5 lazy-loading eager-loading

我有以下代码,我尝试让所有学生(使用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

2 个答案:

答案 0 :(得分:0)

当对象被序列化为json时,这些属性会被序列化,您可以在客户端上使用它们。由于在退出using块后发生序列化,因此在放置上下文后将访问属性。你可以做以下三件事之一:

  1. 使用[JsonIgnore]属性标记未使用的属性。有关详细信息,请参阅here

  2. 创建第二个类,该类仅包含客户端中所需的属性,并使用SelectUser投影到此新的更具体的对象。或者使用auromapper自动进行映射。关于auromapper this可能是一篇很好的文章,可以帮助您入门

  3. 为每个控制器创建一个上下文,在承包商中初始化它,并且只将其置于控制器配置方法的覆盖中。这将确保序列化期间上下文可用。

  4. 从性能角度来看,2是最好的,因为您只发送您需要的内容,并且您可以更灵活地为每个操作定制输出(可能其他操作需要这些字段)。 3是最简单的实现,但是你发送了许多你不需要的数据,并且不必要地访问数据库。 1提供并轻松修复,直到其他人向模型添加新属性,同样,您可能最终得到客户端中的数据,不仅您不需要,而且不应该到达客户端(密码,其他敏感信息)可能会添加到模型中)

答案 1 :(得分:0)

Titan Cernicova是完全正确的,我只想添加一件事:如果你从WebAPI控制器返回一个实体对象你可能有内存问题,可能是服务器上的内存泄漏,不要这样做

因此,一个好的做法是创建一个包含所需属性的数据传输对象:

size

将您的实体对象投射到此并返回。