繁体   English   中英

System.OutOfMemoryException:angularjs中抛出了类型'System.OutOfMemoryException'的异常

[英]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'的异常

这就是问题。 请让我知道我该如何解决?

实际上我为这个问题做了一些事情。

  • 我已经清除了临时文件夹 - 没有工作
  • 我重新启动Visual Studio并清理解决方案,重新启动系统并修复visual studio.-不工作
  • 但是,如果我删除了数据库中的某些行(使用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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM