繁体   English   中英

实体框架关系结果Web Api序列化错误

[英]Entity Framework relational result Web Api serialization error

我在Wep Api项目中使用实体框架。 我的模型是现实的,并符合以下要求:

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Article> Articles { get; set; }
}
public class Article
{
    public int Id { get; set; }
    public int BlogId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }

    public virtual Blog Blog { get; set; }
}

上下文是这样的:

public class BloggingContext: DbContext
{
    public DbSet<Blog> Blogs { get; set; }
    public DbSet<Article> Articles { get; set; }
}

我在asp.net Web Api控制器中使用它。

public class BlogController: ApiController{
      public IEnumerable<Blog> Get(){

           var context = new BloggingContext();

           return context.Blogs.ToList();
      }
}

我的方法是通过延迟加载获取数据,并作为Web Api响应序列化为JSON数据。

context.Blogs.ToList()返回关系数据(我在断点上看到)。

但是Web Api结果有错误。

异常消息:

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

内部异常:

从“ System.Data.Entity.DynamicProxies.Article_D002A1ECE031410435306DCEF780AFF03EBB8BD36DA603662C993107FAEB1917“ ExceptionType”上的“博客”获取值时出错

我设置了WebApiConfig.cs

 var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
 jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
 jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
 config.Formatters.Remove(config.Formatters.XmlFormatter);

您可以尝试禁用代理生成。 至少,如果它不能解决问题,则可能会给您带来更明确的例外。

context.Configuration.ProxyCreationEnabled = false;

老懒加载问题! 好好玩!

因此,首先,当您断点并评估实体时,它本身会触发延迟加载。 这样的实体框架很聪明,但没有帮助。 实际上,如果您不进行调试,则这些相同的属性将为null。

您在此处有2个选项:1.急切加载或2.如前所述,使用传输对象。 但是他们为什么会这样。

  1. 很明显。 通过使用context.Blogs.Include(x => x... etc)您告诉实体框架只是继续并加载它们,因为我们将需要它。

  2. 为什么使用传输对象有效? 为了将数据传输到新对象中,您必须在旧实体内的所有属性上调用Get方法,从而触发延迟加载。 为此,您可以使用第三方软件包,例如AutoMapper,但它们可能会导致开销。

对于API,我个人建议进行Eager加载。 API的要点是您作为开发设计的终点,并限制了可以使用和不能使用的内容。 如果您想要延迟加载,那么我建议使用MVC是更好的选择。

尝试在控制器中使用数据传输对象。在我的情况下,此问题已解决.BlogModel是您必须添加以用作DTO的新类的名称,它具有与实体类相同的属性。

public IEnumerable<Blog> Get(){

       List<BlogModel> listofModels = new List<BlogModel>();
       foreach(var model in whateveristhenameofyourentity.Blogs)
              {
                     BlogModel blogModel = new BlogModel();
                     blogModel.name = model.name;
                     .
                     .
                     .
                     listofModels.Add(BlogModel);
              }
         IEnumerable<BlogModel> models = listofModels.AsIEnumerable();
         return models;
  }

暂无
暂无

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

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