停止多对多自引用实体的加载

时间:2019-03-23 21:54:03

标签: entity-framework json.net

我在实体框架中有很多关系,由于循环无限(使用newtonsoft),导致序列化问题(使用newtonsoft),我得到了:自引用循环检测到错误:

我尝试了Self referencing loop Entity FrameWork

中的选项设置
 config.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling 
= Newtonsoft.Json.ReferenceLoopHandling.Ignore; 

但是它不能解决它。我的课程如下:

public class Job
{
    public int Id { get; set; }
    public string Title { get; set; }
    public virtual ICollection<Tag> Tags { get; set; }
}

public class Tag
{
    public int Id { get; set; }
    public string Title { get; set; }
    public ICollection<Job> Jobs { get; set; }
}

因此在.net中,当我搜索职位时,可以告诉它仅包含标签,之后不包含职位吗?即:

   // How to not include jobs in tags object?
   var jobs = context.Job.Include(x => x.Tags);

1 个答案:

答案 0 :(得分:1)

简单的答案是“不要将实体发送给客户端,请使用视图模型。”

如果您的客户关心的只是一个工作及其标签列表:

[Serializable]
public class JobViewModel
{
    public int JobId { get; set;}
    public string Title { get; set; } 
    public List<TagViewModel> Tags { get; set; } = new List<TagViewModel>();
}
[Serializable]
public class TagViewModel
{
    public int TagId { get; set; }
    public string Title { get; set; }
}

然后,选择所有作业及其标签:(理想情况下,它应该具有Where子句或分页,但例如)

var jobs = context.Jobs.Select(j => new JobViewModel
{
    JobId = j.JobId,
    Title = j.Title,
    Tags = j.Tags.Select(t => new TagViewModel
    {
        TagId = t.TagId,
        Title = t.Title
    }).ToList()
}).ToList();

您可以避免使用AutoMapper进行手动转换,它的ProjectTo<T>方法与EF基于IQueryable的方法很好地集成在一起。

var jobs = context.Jobs
    .ProjectTo<JobViewModel>()
    .ToList();

为什么?

  • 避免循环引用序列化问题。
  • 优化发送到数据库的查询,以仅撤回所需的字段。
  • 减少服务器和客户端上的内存使用。
  • 减少通过服务器之间和客户端之间的线路发送的数据量。
  • 避免向客户端发送过多的数据。 (暴露整个域模型,否则未显示)
  • 避免从客户端接受实体,附加和保存不想要的更改的风险。 (调试器手动更改字段或关联的实体)