System.OutOfMemoryException:类型' System.OutOfMemoryException'的异常。被引入angularjs

时间:2015-05-02 06:23:27

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

我花了几周的时间来解决这个问题。但我仍然无法解决这个问题。

我使用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方法

时,请参阅下面的图片

enter image description here

最后http error function在5或10分钟后命中,并显示以下错误消息。

System.OutOfMemoryException:类型&#39; System.OutOfMemoryException&#39;的异常被抛出

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

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

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

例如,如果我的数据库表少于7行,那么它可以快速运行而不会出现该错误。 但是,如果我的表有超过8行,那么它的工作速度非常慢并抛出错误?的 为什么? 回覆 如果你坚持这个问题,请你分享你的解决方案。

5 个答案:

答案 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来编码这样的引用)来处理重复的引用和循环。