繁体   English   中英

使用EF和WebApi将父/子对象序列化

[英]Serializing Parent/Child Object to with EF and WebApi

我在实体框架中有以下模型:

public class Customer
{
[XmlIgnore]
public virtual ICollection<Customer> Children { get; set; }

public string Name { get; set; }
}

现在我尝试使用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);              
     }
   }
}

当我这样做并使用POST调用该方法时,我收到以下错误:

'ObjectContent`1'类型无法序列化内容类型'application / json的响应主体; 字符集= utf-8的

InnerException:“从'System.Data.Entity.DynamicProxies.Customer'上的'Children'获取值时出错”

InnerException(2):“ObjectContext实例已被释放,不能再用于需要连接的操作。”

customers.Children目前是一个空列表。

我猜这个问题的出现是因为儿童与客户的类型相同,导致“无限序列化循环”。 (我没有更好的词来形容)

我已经尝试过XmlIgnore来防止该属性被序列化但没有效果。

不要将导航属性声明为virtual或禁用延迟加载行为。 默认情况下启用延迟加载,通过创建派生代理类型的实例,然后覆盖virtual属性以添加加载挂钩来实现。 因此,如果您想使用XML序列化程序,我建议您关闭延迟加载:

public class YourContext : DbContext 
{ 
    public YourContext() 
    { 
        this.Configuration.LazyLoadingEnabled = false; 
    } 
}

如果要加载相关实体( Children ),可以使用Include扩展方法作为查询的一部分。 此行为称为Eager Loading

using System.Data.Entity;  // For extension method `Include`

List<Customer> allCustomers = tc.Customers.Include(c=>c.Children).ToList();

这些链接可以帮助您更好地理解我在答案中解释的内容:

如果从导航属性中删除virtual关键字,则POCO实体不符合第二个链接中描述的要求,因此,EF不会创建代理类来延迟加载导航属性。 但是,如果禁用延迟加载,即使导航属性是virtual ,也不会在任何实体中加载它们。 在使用序列化程序时禁用延迟加载是个好主意。 大多数序列化程序通过访问类型实例上的每个属性来工作。

仅仅为了知识:以下也有效:

public class Customer
{
[XmlIgnore,JSonIgnore]
public virtual ICollection<Customer> Children { get; set; }

public string Name { get; set; }
}

神奇的是那里的“JsonIgnore”。

尽管如此:@octavioccl的答案是一个更好的解决方案,需要更多的工作,但创建更好的代码。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM