我花了几周的时间来解决这个问题。但我仍然无法解决这个问题。
我使用http
angularjs
来调用网络API服务
$http({
method: 'GET',
url: rootUrl + '/api/Project/ProjectList',
headers: {
'Content-Type': "application/json; charset=utf-8"
}
}).success(function (response) {
$scope.ProjectList = response;
}).error(function (response, errorCode) {
if (errorCode == 444) {
}
})
我已经在服务器端和客户端编码中设置了断点。
当我调用该服务时,服务器端方法快速命中
我的服务器端方法( am使用带实体框架的MVC WEB API )
[ActionName("ProjectList")]
[HttpGet]
public IList<Project> ProjectList(Project projectModel)
{
return objIProjectService.ListOfProject();
}
我检查过,服务返回8条记录(数据库中有8行),并在objIProjectService.ListOfProject();
这一行有一个断点。
http.success and http.error
回调函数的速度非常慢。
在我调用http
方法
最后http error function
在5或10分钟后命中,并显示以下错误消息。
System.OutOfMemoryException:类型&#39; System.OutOfMemoryException&#39;的异常被抛出
这就是问题所在。请让我知道我该如何解决?
实际上我为这个问题做了一些事情。
sql server 2008 r2
),那么它正在运行。 例如,如果我的数据库表少于7行,那么它可以快速运行而不会出现该错误。 但是,如果我的表有超过8行,那么它的工作速度非常慢并抛出错误?的 为什么? 回覆 如果你坚持这个问题,请你分享你的解决方案。
答案 0 :(得分:11)
我认为问题在于序列化程序正在访问项目类的所有相关属性,因此不是直接返回实体框架类,而是创建一个新类来表示您希望通过api发送的数据(研究进一步深入DTO课程以获取更多信息)
您可以使用Select
Linq方法获取使用EF调用数据填充的新dto类的列表。
var projects = objIProjectService.ListOfProject();
return projects.Select(p => new ProjectDTO() {
ID = p.Id
//... other properties of DTO class
}).ToList();
更好的是,如果你把这个选择方法放入你的EF查询(即context.projects.Select(/* select info here */).ToList()
),你可以确保EF只带回你需要的字段
构建API时,请始终检查json / XML响应,确保序列化数据包含您希望生成的内容。使用实体框架,这个响应最终会变得非常庞大,因为它会浏览所有相关的表,提取所有链接的信息,然后尝试将其序列化。
作为个人偏好我总是喜欢返回IHttpActionResult
它允许你管理发送回客户端的内容,特别是当出现问题时,控制器有许多方法可以用来创建它们,即OK(), BadRequest(), InternalServerError()
...
答案 1 :(得分:2)
打开Sql Server Profiller并观察EF生成的sql查询和结果。然后尝试在sql窗口执行这个原始查询。可能你会在此之后理解。
答案 2 :(得分:0)
这里的问题是信息的序列化花费了很多时间。您正在访问项目类的所有相关类,这可能会在处理内存方面时造成重大损害。
您可以通过两种方式解决此问题:
一个是返回你的承诺,然后获取数据:
return $http({
method: 'GET',
url: rootUrl + '/api/Project/ProjectList',
headers: {
'Content-Type': "application/json; charset=utf-8"
}
}).then(function (response) {
第二个选项将在代码中,使用Entity框架或linq查询。
使用select查询降低服务器端和客户端的负担,如下所示:
var projectsQuery = from p in ProjectModel as pm where pm.Id = p.Id select p.SomeValue
return projectsQuery
通过这种方式,您将能够降低数据序列化的负担,并可能避免outOfMemoryExcexption。
这里没有必要打开Sql Profiler,因为服务器端的数据是合理的。
答案 3 :(得分:0)
HTTP规范没有对帖子施加特定的大小限制。 GET查询的问题是参数嵌入在URL中,其大小有限(此限制取决于浏览器和服务器)。 不要对大数据使用GET查询使用POST。
还有另一个话题如果您正在使用MVC而且您正在处理大数据, 你需要使用这个。
<appSettings>
<add key="aspnet:MaxJsonDeserializerMembers" value="150000" />
</appSettings>
或
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="1000000" />
</requestFiltering>
</security>
来自:MSDN
我希望这些可以解决你的问题。
答案 4 :(得分:0)
进一步了解Chris Warnes的建议并描述可能的原因。
让我猜一下......你使用启用了延迟加载的实体框架。因此,在序列化期间,您拥有的每个导航属性有时会懒惰地递归加载数据。例如:Project
包含Worker
,其中包含对Project
等某些导航属性中相同WorkerProjects
的引用。
序列化程序试图理解它,但它没有,没有一些提示。
检查实际情况的最简单方法是禁用实体框架延迟加载并在ToList()
之后和return
之前获取该断点。
顺便说一句。将这种结构序列化为JSON是 - 有点 - 不可能。您需要有外部机制(例如cycle.js使用XPath来编码这样的引用)来处理重复的引用和循环。