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