c# - EF 6 代码首先将 IEnumerable<> 转换为 Json "Self referencing loop detected with type..."

标签 c# json entity-framework stored-procedures

我需要返回完整的 json 对象(包括子 json 对象),但是我收到错误...该实体是从数据库导入的。

错误

Self referencing loop detected with type 'System.Data.Entity.DynamicProxies.PhoneNumber_C240BC86FA502D917EFDFC445D42023BBD311F87B9B79339114CAC180EEC83F1'. Path '[0].UserProfile.PhoneNumbers[0].PhoneNumberType.PhoneNumbers'.

实体

[Table("UserProfile")]
public partial class UserProfile
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public UserProfile()
    {
        PhoneNumbers = new HashSet<PhoneNumber>();
        Users = new HashSet<User>();
        UserEmails = new HashSet<UserEmail>();
    }

    public int Id { get; set; }

    [Column(TypeName = "datetime2")]
    public DateTime? dte_modified { get; set; }

    public string firstname { get; set; }

    public string lastname { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<PhoneNumber> PhoneNumbers { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<User> Users { get; set; }

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
    public virtual ICollection<UserEmail> UserEmails { get; set; }
}

API Controller

    [HttpGet]
    [Route("")]
    public IHttpActionResult Get()
    {
        var result = _repository.GetAllUsers();

        return Json(result);
    }

存储库

        public IEnumerable<User> GetAllUsers()
    {
        return _context.Users.ToList();
    }

最佳答案

您的问题是由 Entity Framework 的一项名为 Lazy Loading 的功能引起的,默认情况下启用,并且抛出该异常是因为您的 json 序列化程序正在尝试访问 User 实例上的每个属性。属性访问触发延迟加载,因此更多实体被序列化。在这些实体上访问属性,甚至加载更多实体,并且根据您的情况,这可能会结束尝试序列化自引用循环,这是由您的 json 序列化程序检测到的。

如果你只想加载 User 实体的标量属性,你可以在你的上下文中禁用延迟加载:

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

如果您想加载相关实体作为查询的一部分,您可以使用 Include 扩展方法:

public IEnumerable<User> GetAllUsers()
{
    return _context.Users.Include(u=>u.Users).Include(u=>u.UserEmails).ToList();
}

另一种解决方案是,正如@DOTang 所建议的那样,创建一个 DTO类以仅投影您需要在 View 中显示的数据。

更新:

现在我找到了一个优秀的reference解释解决这个问题的几种方法。

关于c# - EF 6 代码首先将 IEnumerable<> 转换为 Json "Self referencing loop detected with type...",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35445318/

相关文章:

c# - 调整 MVC 4 WebApi XmlSerializer 丢失 nameSpace

android - RealmObject 到 JSON

php - 读取图像 block : Fatal Error when converting SVG into PNG

entity-framework - 使用 TextTransform.exe 从 edmx 文件生成代码

entity-framework - Entity Framework 和表值参数

c# - Xamarin Android 警报管理器问题

c# - 如何仅选择在一列中具有唯一值的行?

javascript - 使用 FFMPEG 的 ASP.NET Core 5.0 MVC HLS 转码

json - jq 根据属性的现有值修改值

entity-framework - 无法在 ASP.NET Core 项目中安装 Microsoft.EntityFrameworkCore