【问题标题】:System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown in angularjsSystem.OutOfMemoryException:在 angularjs 中引发了“System.OutOfMemoryException”类型的异常
【发布时间】:2015-07-12 00:17:47
【问题描述】:

我为这个问题花了几个星期。但我仍然无法解决这个问题。

我正在通过在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(); 这一行。

一切都很顺利。但我的(回复)http.success and http.error 回调函数运行速度非常慢。

请参阅下图了解我调用 http 方法时的性能

在 5 或 10 分钟后,http error function 终于被击中,并出现以下错误消息。

System.OutOfMemoryException:抛出了“System.OutOfMemoryException”类型的异常

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

其实我为这个问题做了点什么。

  • 我已清除临时文件夹 - 无法正常工作
  • 我已重新启动 Visual Studio 并清理解决方案,重新启动我的系统并修复 Visual Studio.- 不工作
  • 但如果我删除了数据库中的一些行(我正在使用sql server 2008 r2),那么它就可以工作了。

例如,如果我的数据库表的行数少于 7 行,那么它的运行速度很快,不会出现该错误。 但是如果我的表超过 8 行,那么它的工作速度非常慢并抛出了错误?? 为什么? 回覆 如果您遇到此问题,请分享您的解决方案。

【问题讨论】:

  • 您需要将objIProjectService.ListOfProject();函数的实现、数据库表的结构以及示例数据发布在哪里可以正常工作以及哪里会出现错误
  • 那个代码是:return context.products.ToList()
  • 尝试使用 JSON 作为返回类型,序列化对象并将其发送回
  • 那么返回的模型和表中的数据呢?这是序列化到您的模型以返回具有循环引用的问题吗?

标签: c# sql-server asp.net-mvc angularjs asp.net-web-api


【解决方案1】:

我认为问题在于序列化程序正在访问您项目类上的所有相关属性,因此与其直接返回实体框架类,不如创建一个新类来表示您希望通过 api 发送的数据(研究进一步了解 DTO 类以获取更多信息)

您可以使用Select Linq 方法获取新 dto 类的列表,其中填充了您的 EF 调用中的数据。

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,它允许您管理发送回客户端的内容,尤其是在出现问题时,控制器有许多方法可以用来创建这个,即@987654325 @...

【讨论】:

  • 感谢您的解释。
【解决方案2】:

打开 Sql Server Profiler 并观察 EF 生成的 sql 查询和结果。然后尝试在 sql 窗口上执行这个原始查询。说不定你会明白的。

【讨论】:

    【解决方案3】:

    这里的问题是信息的序列化需要很长时间。您正在访问项目类的所有相关类,这可能会在处理内存方面造成重大损害。

    您可以通过两种方式解决此问题:

    一种是返回你的承诺,然后获取数据:

     return $http({
                   method: 'GET',
                   url: rootUrl + '/api/Project/ProjectList',
                   headers: {
                       'Content-Type': "application/json; charset=utf-8"
                   }
               }).then(function (response) {
    

    第二个选项将在代码中,使用实体框架或 linq 查询。

    使用选择查询来减轻服务器端和客户端的负担如下:

        var projectsQuery = from p in ProjectModel as pm where pm.Id = p.Id select p.SomeValue
    return projectsQuery 
    

    通过这种方式,您将能够减轻数据序列化的负担,并可能避免 outOfMemoryExcexption。

    这里不需要打开 Sql Profiler,因为来自服务器端的数据来得正是时候。

    【讨论】:

      【解决方案4】:

      HTTP 规范没有对帖子施加特定的大小限制。 GET 查询的问题在于参数嵌入在 URL 中,其大小受到限制(此限制取决于浏览器和服务器)。 不要对大数据使用 GET 查询,请使用 POST 查询。

      还有另一个话题如果你正在使用 MVC 并且你在处理大数据, 你需要使用这个。

      <appSettings>
        <add key="aspnet:MaxJsonDeserializerMembers" value="150000" />
      </appSettings>
      

      <system.webServer>
      <security>
          <requestFiltering>
              <requestLimits maxAllowedContentLength="1000000" />
          </requestFiltering>
      </security>
      

      来自:MSDN

      希望这些能解决你的问题。

      【讨论】:

        【解决方案5】:

        进一步了解 Chris Warnes 的建议并描述可能的原因。

        让我猜猜……您使用启用了延迟加载的实体框架。因此,在序列化期间,您拥有的每个导航属性有时都会延迟和递归地加载数据。例如:Project 包含 Worker,其中包含在某些导航属性中对相同 Project 的引用,例如 WorkerProjects

        Serializer 试图理解它,但它不能,没有一些提示。 检查发生了什么的最简单方法是禁用实体框架延迟加载并在ToList() 之后和return 之前获取断点。

        顺便说一句。将这种结构序列化为 JSON - 有点 - 是不可能的。您需要有外部机制(例如cycle.js 使用XPath 来编码这样的引用)来处理重复的引用和循环。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-01-14
          • 2013-08-28
          • 2015-07-18
          • 2011-02-14
          相关资源
          最近更新 更多