Web API响应导致“System.OutOfMemoryException”

问题描述 投票:1回答:1

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

[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类。

c# asp.net-web-api out-of-memory
1个回答
1
投票

看起来您正在直接从Web API(通过其内置的JSON Serializer)返回Entity Framework对象。一般规则是永远不要这样做,因为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 Object属性,这是另一个EF对象(或EF对象的集合),那么您需要将这些属性转换为未链接到EF的“简单”对象。

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

© www.soinside.com 2019 - 2024. All rights reserved.