简体   繁体   English

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

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

I have the following model inside an entity framework: 我在实体框架中有以下模型:

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

public string Name { get; set; }
}

Now I try to serialize this using web api: 现在我尝试使用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);              
     }
   }
}

When I do this and call the method using POST I receive the following error: 当我这样做并使用POST调用该方法时,我收到以下错误:

The 'ObjectContent`1' type failed to serialize the response body for content type 'application/json; 'ObjectContent`1'类型无法序列化内容类型'application / json的响应主体; charset=utf-8 字符集= utf-8的

InnerException: "Error getting value from 'Children' on 'System.Data.Entity.DynamicProxies.Customer" InnerException:“从'System.Data.Entity.DynamicProxies.Customer'上的'Children'获取值时出错”

InnerException(2): "The ObjectContext instance has been disposed and can no longer be used for operations that require a connection." InnerException(2):“ObjectContext实例已被释放,不能再用于需要连接的操作。”

customers.Children is currently an empty List. customers.Children目前是一个空列表。

My guess this problem occurs because Children is of the same type as Customer causing an "infinite serialization loop". 我猜这个问题的出现是因为儿童与客户的类型相同,导致“无限序列化循环”。 (I got no better words to describe that) (我没有更好的词来形容)

I already tried XmlIgnore to prevent that property to be serialized but with no effect. 我已经尝试过XmlIgnore来防止该属性被序列化但没有效果。

Don't declare that navigation property as virtual or disable Lazy Loading behavior. 不要将导航属性声明为virtual或禁用延迟加载行为。 Lazy loading is enable by default and is achieved by creating instances of derived proxy types and then overriding virtual properties to add the loading hook. 默认情况下启用延迟加载,通过创建派生代理类型的实例,然后覆盖virtual属性以添加加载挂钩来实现。 So, if you want to work with XML serializer I recommend you turn off lazy loading: 因此,如果您想使用XML序列化程序,我建议您关闭延迟加载:

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

In case you want to load the related entity ( Children ), you can use the Include extension method as part of a query. 如果要加载相关实体( Children ),可以使用Include扩展方法作为查询的一部分。 This behavior is called Eager Loading . 此行为称为Eager Loading

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

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

These links can help you to understand better what I explain in my answer: 这些链接可以帮助您更好地理解我在答案中解释的内容:

If you remove the virtual keyword from your navigation properties, the POCO entity not meet the requirements described in the second link, so, EF won't create a proxy class to lazy load your navigation properties. 如果从导航属性中删除virtual关键字,则POCO实体不符合第二个链接中描述的要求,因此,EF不会创建代理类来延迟加载导航属性。 But if you disabled lazy loading, even when your navigation properties are virtual , they won't be loaded in any entity. 但是,如果禁用延迟加载,即使导航属性是virtual ,也不会在任何实体中加载它们。 It's good idea disable lazy loading when you are using a serializer. 在使用序列化程序时禁用延迟加载是个好主意。 Most serializers work by accessing each property on an instance of a type. 大多数序列化程序通过访问类型实例上的每个属性来工作。

Just for the sake of knowledge: The following also works: 仅仅为了知识:以下也有效:

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

public string Name { get; set; }
}

The magic is "JsonIgnore" there. 神奇的是那里的“JsonIgnore”。

Nonetheless: @octavioccl 's answer is a much better solution which requires more work but creates better code. 尽管如此:@octavioccl的答案是一个更好的解决方案,需要更多的工作,但创建更好的代码。

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

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