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

本文关键字:API 序列化 错误 Web 结果 框架 关系 实体 | 更新日期: 2023-09-27 18:30:57

我在我的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();
      }
}

我的方法是使用延迟加载获取数据,并将 JSON 数据序列化为 Web API 响应。

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

但是Web Api结果有错误。

异常消息:

"

对象内容"1"类型无法序列化 的响应正文 内容类型"应用程序/JSON";字符集=UTF-8

内部异常:

从"博客"获取值时出错 'System.Data.Entity.DynamicProxies.Article_D002A1ECE031410435306DCEF780AFF03EBB8BD36DA603662C993107FAEB1917 "ExceptionType": "Newtonsoft.Json.JsonSerializationException

我设置了我的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);

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

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

context.Configuration.ProxyCreationEnabled = false;

旧的懒惰加载问题!真好玩!

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

您在这里有 2 个选项,1。急切负载或 2。如前所述,使用传输对象。但他们为什么会。

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

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

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

尝试在控制器中使用数据传输对象。就我而言,这解决了问题。BlogModel 是必须添加才能使用的新类的名称,因为它与实体类具有相同的属性 DTO.It。

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;
  }