我有以下代码,我尝试让所有学生(使用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
答案 0 :(得分:0)
当对象被序列化为json时,这些属性会被序列化,您可以在客户端上使用它们。由于在退出using块后发生序列化,因此在放置上下文后将访问属性。你可以做以下三件事之一:
使用[JsonIgnore]
属性标记未使用的属性。有关详细信息,请参阅here
创建第二个类,该类仅包含客户端中所需的属性,并使用Select
将User
投影到此新的更具体的对象。或者使用auromapper自动进行映射。关于auromapper this可能是一篇很好的文章,可以帮助您入门
为每个控制器创建一个上下文,在承包商中初始化它,并且只将其置于控制器配置方法的覆盖中。这将确保序列化期间上下文可用。
从性能角度来看,2是最好的,因为您只发送您需要的内容,并且您可以更灵活地为每个操作定制输出(可能其他操作需要这些字段)。 3是最简单的实现,但是你发送了许多你不需要的数据,并且不必要地访问数据库。 1提供并轻松修复,直到其他人向模型添加新属性,同样,您可能最终得到客户端中的数据,不仅您不需要,而且不应该到达客户端(密码,其他敏感信息)可能会添加到模型中)
答案 1 :(得分:0)
因此,一个好的做法是创建一个包含所需属性的数据传输对象:
size
将您的实体对象投射到此并返回。