我开发了一个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类。
看起来您正在直接从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等工具使其更加结构化(一旦配置)将随时随地为您进行映射。