Ole*_*ers 4 c# serialization json entity-framework asp.net-web-api
我在实体框架中有以下模型:
public class Customer
{
[XmlIgnore]
public virtual ICollection<Customer> Children { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
现在我尝试使用 web api 序列化它:
public class CustomerController:ApiController {
public HttpResponseMessage GetAll()
{
using (var tc = new DataContext())
{
List<Customer> allCustomers = tc.Customers.ToList();
return Request.CreateResponse(HttpStatusCode.OK, allCustomers);
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我这样做并使用 POST 调用该方法时,我收到以下错误:
“ObjectContent`1”类型无法序列化内容类型“application/json”的响应主体;字符集=utf-8
InnerException:“从‘System.Data.Entity.DynamicProxies.Customer’上的‘Children’获取值时出错”
InnerException(2):“ObjectContext 实例已被释放,不能再用于需要连接的操作。”
customer.Children 目前是一个空列表。
我猜这个问题的发生是因为 Children 与 Customer 属于同一类型,导致“无限序列化循环”。(我没有更好的词来形容)
我已经尝试过 XmlIgnore 来防止该属性被序列化,但没有效果。
不要将该导航属性声明为virtual
或禁用延迟加载行为。默认情况下启用延迟加载,它是通过创建派生代理类型的实例,然后覆盖virtual
属性以添加加载钩子来实现的。因此,如果您想使用 XML 序列化程序,我建议您关闭延迟加载:
public class YourContext : DbContext
{
public YourContext()
{
this.Configuration.LazyLoadingEnabled = false;
}
}
Run Code Online (Sandbox Code Playgroud)
如果要加载相关实体 ( Children
),可以使用Include
扩展方法作为查询的一部分。这种行为称为Eager Loading。
using System.Data.Entity; // For extension method `Include`
List<Customer> allCustomers = tc.Customers.Include(c=>c.Children).ToList();
Run Code Online (Sandbox Code Playgroud)
这些链接可以帮助您更好地理解我在回答中的解释:
如果您virtual
从导航属性中删除关键字,则 POCO 实体不符合第二个链接中描述的要求,因此,EF 不会创建代理类来延迟加载您的导航属性。但是如果你禁用了延迟加载,即使你的导航属性是virtual
,它们也不会被加载到任何实体中。在使用序列化程序时禁用延迟加载是个好主意。大多数序列化程序通过访问类型实例上的每个属性来工作。
归档时间: |
|
查看次数: |
3359 次 |
最近记录: |