【问题标题】:C# Entity Framework 6 with ASP.Net web API returning empty array in JSON response带有 ASP.Net Web API 的 C# Entity Framework 6 在 JSON 响应中返回空数组
【发布时间】:2017-05-05 11:19:00
【问题描述】:

这是我用来在“工单”控制器中处理 GET 请求的代码:

    // GET: api/WorksOrders/5
    /// <summary>
    /// Fetches the Works Order with corresponding ID (pkOrderItemID)
    /// </summary>
    [Authorize]
    public OrderItem Get(int id)
    {
        using (var entities = new customappsEntities())
        {
            return entities.OrderItems.FirstOrDefault(e => e.pkOrderItemID == id);
        }
    }

运行时,我在 JSON 响应中收到以下错误消息:

 "Error getting value from 'OrderItemDepartments' on 'System.Data.Entity.DynamicProxies.OrderItem_501562E50E13B847D4A87F7F2DEC7C8CEDAF127355CB4FC30E12653275CE6412'.",

我可以通过添加来解决这个问题

entities.Configuration.ProxyCreationEnabled = false;

这会返回整个表格,但底部有一组空数组,例如 JSON 格式的响应如下所示:

{
  "$id": "1",
  "pkOrderItemID": 271,
  "StartedOn": "2015-01-01T00:00:00",
  "CompletedOn": "2014-10-15T00:00:00",
  "Costs": [],
  "Dispatches": []
}

数组似乎是数据库中的外键关系,我相信它们返回空,因为它卡在自引用循环中(我能够收到该错误消息几次,但我无法从那以后重新创建它)。我试过添加

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Re‌​ferenceLoopHandling = ReferenceLoopHandling.Ignore;

发件人:Self referencing loop detected - Getting back data from WebApi to the browser

以及来自相同或相似线程的许多其他解决方案,但它并没有解决问题。我所有的数据类都是由 Entity Framework 自动生成的,所以我无法修改它们,也许这是设置 Web API 的错误方式?

任何帮助找出数组返回空的原因将不胜感激。 谢谢你。

更新

这是展示fk关系的DataModel Diagram的截图

【问题讨论】:

    标签: c# asp.net arrays json entity-framework


    【解决方案1】:

    不要通过 JSON 序列化返回 POCO 或匿名对象以外的任何内容。 Entity Framework 对象具有您不希望看到的巨大开销,并且通常具有序列化程序无法处理的循环关系(而且您不希望,即使您将其配置为允许它们)。

    创建一个 POCO 或返回一个选择:

    [Authorize]
    public MyOrderItem Get(int id)
    {
        using (var entities = new customappsEntities())
        {
            var item = entities.OrderItems.FirstOrDefault(e => e.pkOrderItemID == id);
            return new MyOrderItem()
            {
                 StartedOn = item.StartedOn,
                 ...
            };
        }
    }
    

    正确使用 JSON 的关键是只返回你需要的东西

    更新

    由于该项目包含子项目,您需要确保您也有这些子项目的 POCO:

    例如

    var myOrderItem = new MyOrderItem()
    {
         StartedOn = item.StartedOn,
         Costs = new List<MyCost>();  // <=== This can also go in the default constructor
         ...
    };
    foreach (var cost in item.Costs)
    {
         myOrderItem.Costs.Add(new MyCost()
         {
             Value = cost.Value
             ...
         });
    }
    return myOrderItem;
    

    另一个更新

    这很奇怪。它当然应该给你你的记录。您也可以尝试使用.Include().Select()FirstOrDefault() 而不是只使用FirstOrDefault(),以保证相关记录已预先加载。

    例如:

    entities.OrderItems.Include(x=>x.Costs).Select(x=>x).FirstOrDefault();
    

    【讨论】:

    • 感谢您的回复。我已经添加了这个,但我仍然得到空数组。我添加了一个断点,它说 item.Costs 的 count = 0 如果有帮助的话,这是一个 ICollection
    • 你在哪里添加了断点?您能展示一下您是如何尝试用数据填充新 POCO 的吗?
    • 嗨,我已经在返回行添加了断点,这样我就可以检查正在获取的值。以下是我目前尝试填充它的方式:return new OrderItem() { pkOrderItemID = item.pkOrderItemID, StartedOn = item.StartedOn, CompletedOn = item.CompletedOn, Costs = item.Costs, Dispatches = item.Dispatches }; 我还尝试了使用 .ToArray() 和 .ToList() 的成本。抱歉,评论格式不佳。
    • 我假设成本是另一个表?对于这些对象,您也需要一个 POCO。我将添加一个示例,但我必须猜测您的对象结构。
    • 感谢您的帮助。成本确实是另一个表,它们与存储在成本表中的外键链接(实体框架在图表中显示了它自动生成的链接,因此我假设它设置正确)。我已经从您的编辑中添加了代码,但问题是 item.Costs 返回为空,因此 foreach 循环不会运行。
    【解决方案2】:

    添加 Newtonsoft Json 库并返回这样的结果

    JsonSerializerSettings jss = new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
        return JsonConvert.SerializeObject(result, Formatting.Indented, jss);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-05
      • 2019-02-13
      • 1970-01-01
      • 2017-06-07
      相关资源
      最近更新 更多