C# Entity Framework 6与ASP.Net Web API返回JSON响应中的空数组。
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.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
来自:自引用循环检测 - 从WebApi获取数据返回到浏览器
以及同样或类似的线程中的许多其他解决方案,但它没有解决问题。我所有的数据类都是由Entity Framework自动生成的,所以我无法修改它们,也许这是设置Web API的错误方式?
将不胜感激地接受任何帮助以弄清楚为什么数组返回为空。
谢谢。
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
解决了问题!非常感谢您所做的所有帮助。谢谢。
很高兴能解决问题。但我仍然想不出为什么以前无法解决这个问题。
在使用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响应。