C# Entity Framework 6与ASP.Net Web API返回JSON响应中的空数组。

17 浏览
0 Comments

C# Entity Framework 6与ASP.Net Web API返回JSON响应中的空数组。

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

// GET: api/WorksOrders/5

///

/// 获取具有对应ID(pkOrderItemID)的工单

///

[Authorize]

public OrderItem Get(int id)

{

using (var entities = new customappsEntities())

{

return entities.OrderItems.FirstOrDefault(e => e.pkOrderItemID == id);

}

}

当运行此代码时,我在JSON响应中收到以下错误信息:

"无法从'System.Data.Entity.DynamicProxies.OrderItem_501562E50E13B847D4A87F7F2DEC7C8CEDAF127355CB4FC30E12653275CE6412'的'OrderItemDepartments'获取值。"

我可以通过添加以下代码来解决此问题:

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;

来自:自引用循环检测 - 从WebApi获取数据返回到浏览器

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

将不胜感激地接受任何帮助以弄清楚为什么数组返回为空。

谢谢。

0
0 Comments

C# Entity Framework 6与ASP.Net Web API返回JSON响应中的空数组问题的原因是,不能返回除POCOs或匿名对象之外的任何东西进行JSON序列化。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的关键是只返回您需要的内容

更新:

由于项目包含子项目,您需要确保这些项目也是POCOs:

例如:

var myOrderItem = new MyOrderItem()
{
     StartedOn = item.StartedOn,
     Costs = new List(),  // <=== 这也可以放在默认构造函数中
     ...
};
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,item.Costs是一个ICollection,如果这有帮助的话。

您在哪里添加了断点?您可以展示一下您如何使用数据填充新的POCOs吗?

嗨,我在返回行上添加了断点,以便我可以检查被提取的值。这是我当前尝试填充它的方式:

return new OrderItem()
{
    pkOrderItemID = item.pkOrderItemID,
    StartedOn = item.StartedOn,
    CompletedOn = item.CompletedOn,
    Costs = item.Costs,
    Dispatches = item.Dispatches
};

我也尝试了使用.ToArray()和.ToList()的Costs。对于糟糕的注释格式化,我感到抱歉。

我假设costs是另一个表?您需要为这些对象创建一个POCO。我将添加一个示例,但我必须猜测您的对象结构。

谢谢您的帮助。Costs确实是另一个表,它们与一个存储在costs表中的外键链接在一起(Entity Framework在自动生成的图表中显示了该链接,因此我认为它设置正确)。我已经添加了您编辑的代码,但问题是item.Costs为空,所以foreach循环不运行。

如果有关联的数据,并且外键设置正确,那么它不应该为空。如果您不使用include,EF将按需加载它们。请检查您的数据库,看看是否有与该主项目记录相关的Costs记录。

再次感谢您的帮助,我已经检查了数据库,确实有该记录的数据。我想现在又回到了起点!如果您有更多的想法,请给我提供。我已经在原始帖子中附上了屏幕截图,显示了关系。谢谢。

这真的很奇怪。它肯定应该给你记录。您还可以尝试使用.Include()结合.Select()First()而不仅仅是FirstOrDefault()来确保预加载相关记录。上面添加了示例。

添加.Include.Select解决了问题!非常感谢您所做的所有帮助。谢谢。

很高兴能解决问题。但我仍然想不出为什么以前无法解决这个问题。

0
0 Comments

在使用C# Entity Framework 6与ASP.Net Web API时,可能会遇到返回空数组的JSON响应的问题。下面将介绍该问题的出现原因以及解决方法。

问题出现的原因是,默认情况下,ASP.Net Web API使用.NET Framework的自带JSON序列化程序来处理对象的序列化。但是,该序列化程序在处理带有循环引用的对象时会出现问题,导致返回的JSON响应中的数组为空。为了解决这个问题,我们需要添加Newtonsoft Json库,并使用其提供的JsonConvert类进行序列化。

解决方法是首先添加Newtonsoft Json库的引用,然后在代码中使用下面的方法来序列化对象并返回结果:

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

上述代码中,我们创建了一个JsonSerializerSettings对象,并将其ReferenceLoopHandling属性设置为Ignore,以忽略循环引用。然后,我们使用JsonConvert类的SerializeObject方法来序列化对象,并指定格式化选项和JsonSerializerSettings对象。

通过以上操作,我们成功解决了C# Entity Framework 6与ASP.Net Web API返回空数组的JSON响应的问题。通过使用Newtonsoft Json库进行序列化,我们能够正确处理带有循环引用的对象,并返回正确的JSON响应。

0