WebAPI 响应导致 "System.OutOfMemoryException"

WebAPI response causes "System.OutOfMemoryException"

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

[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,每个 OEReference 都包含几个 IAReference,这已经打破了。其余字段非常简单。 我在 .Net 4.7.1.

中使用 HttpClient class

看起来您正在 returning Entity Framework 直接来自 Web API 的对象(通过其内置的 JSON 序列化程序)。一般规则是永远不要这样做,因为 JSON 序列化程序将尝试序列化它能找到的所有内容。但是对于具有像您这样的关系的 EF 对象,它将不知道在哪里停止,从而导致引用循环错误甚至内存不足错误。

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

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

一种快速而简单的方法是使用匿名对象,例如:

// 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 的 'simple' 对象。

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