WebAPI响应导致“System.OutOfMemoryException”

时间:2017-12-20 16:27:53

标签: c# asp.net-web-api out-of-memory

我开发了一个WebAPI服务,它在响应中返回一组复杂的自定义对象。 他们的一些领域有多对多的关系。例如:

[Table("OEReferences", Schema = "public")]
public class OEReference
{

    [NotMapped]
    public IList<IAReference> IAReferences{ get; set; }

}

[Table("IAReferences", Schema = "public")]
public class IAReference
{

    [NotMapped]
    public IList<OEReference> OEReferences{ get; set; }

}

每个OEReference对象都有一个IAReferences列表,同时每个IAReference对象都有一个OEReference列表(包括第一个)及其对应的IAReferences列表等等。它永远不会停止。

有时我会遇到内存不足异常。这是什么原因?我该怎样预防呢?

只有约50个OEReference,它们每个都包含几个IAReferences。其余的领域非常简单。 我在.Net 4.7.1中使用HttpClient类。

1 个答案:

答案 0 :(得分:1)

看起来您正在直接从Web API返回Entity Framework对象(通过其内置的JSON Serializer)。一般规则是永远不要这样做,因为JSON Serializer将尝试序列化它能找到的所有东西。但是如果EF对象具有你的关系,它就不会知道停止的位置,导致参考循环错误甚至内存不足错误。

相反,您需要从EF对象中获取所需内容,或者更准确地说:您的API调用者需要什么。

解决方案是创建Objects / ViewModels,它复制调用者需要的EF对象部分,填充EF对象中的部分,然后返回它们。

快速而肮脏的方法是使用匿名对象,例如:

// Instead of "return EF_Item":
return new
{
    Item = new
    {
        Id = EF_Item.Id,
        Description = EF_Item.Description,
        Things = MapThings(EF_Item.Things) // helper function that you need to provide
    }
};

一个好的经验法则是只将EF对象中的简单属性(数字,布尔值,字符串,日期时间)分配给ViewModel项。一旦遇到另一个EF对象(或EF对象集合)的EF对象属性,您就需要将这些属性转换为未链接到EF的“简单”对象。

更结构化的方法是使用ViewModel类,您可以使用AutoMapper之类的工具使其更加结构化(一旦配置)将随时随地为您进行映射。