C# 在EF 6中检测到循环参考

C# 在EF 6中检测到循环参考,c#,entity-framework,json.net,C#,Entity Framework,Json.net,好的,我得到这个错误: 序列化“System.Data.Entity.DynamicProxies.Asset_AED71699FAD07BF6F823A5F022DB9888F62EBBD9E422BBB11D7A191CD784288”类型的对象时检测到循环引用 我明白它的意思。我的代码是从VisualStudioTools生成的,它生成了我所有具有虚拟导航属性的POCO,并映射了关系。 我很高兴,我想懒惰的加载 下面是我的用户类的一个示例: public partial class Use

好的,我得到这个错误:

序列化“System.Data.Entity.DynamicProxies.Asset_AED71699FAD07BF6F823A5F022DB9888F62EBBD9E422BBB11D7A191CD784288”类型的对象时检测到循环引用

我明白它的意思。我的代码是从VisualStudioTools生成的,它生成了我所有具有虚拟导航属性的POCO,并映射了关系。 我很高兴,我想懒惰的加载

下面是我的用户类的一个示例:

public partial class User : IdentityUser
{
    public User()
    {
        this.Assets = new List<Asset>();
        this.Categories = new List<Category>();
        this.Collections = new List<Collection>();
        this.Comments = new List<Comment>();
        this.LocalIntegrations = new List<LocalIntegration>();
        this.Pages = new List<Page>();
        this.Ratings = new List<Rating>();
        this.Themes = new List<Theme>();
        this.ForbiddenCategories = new List<Category>();
        this.ForbiddenPages = new List<Page>();
    }

    public string CompanyId { get; set; }
    public string CreatedById { get; set; }
    public string ModifiedById { get; set; }
    public System.DateTime DateCreated { get; set; }
    public Nullable<System.DateTime> DateModified { get; set; }
    public System.DateTime LastLoginDate { get; set; }
    public string Title { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string Email { get; set; }
    public string JobTitle { get; set; }
    public string Telephone { get; set; }
    public string Mobile { get; set; }
    public string Photo { get; set; }
    public string LinkedIn { get; set; }
    public string Twitter { get; set; }
    public string Facebook { get; set; }
    public string Google { get; set; }
    public string Bio { get; set; }
    public string CompanyName { get; set; }
    public string CredentialId { get; set; }
    public bool IsLockedOut { get; set; }
    public bool IsApproved { get; set; }
    public bool CanEditOwn { get; set; }
    public bool CanEdit { get; set; }
    public bool CanDownload { get; set; }
    public bool RequiresApproval { get; set; }
    public bool CanApprove { get; set; }
    public bool CanSync { get; set; }
    public bool AgreedTerms { get; set; }
    public bool Deleted { get; set; }

    public virtual Company Company { get; set; }
    public virtual User CreatedBy { get; set; }
    public virtual User ModifiedBy { get; set; }
    public virtual ICollection<Asset> Assets { get; set; }
    public virtual ICollection<Category> Categories { get; set; }
    public virtual ICollection<Collection> Collections { get; set; }
    public virtual ICollection<Comment> Comments { get; set; }
    public virtual ICollection<LocalIntegration> LocalIntegrations { get; set; }
    public virtual ICollection<Page> Pages { get; set; }
    public virtual ICollection<Rating> Ratings { get; set; }
    public virtual ICollection<Theme> Themes { get; set; }
    public virtual ICollection<Group> MemberOf { get; set; }
    public virtual ICollection<Category> ForbiddenCategories { get; set; }
    public virtual ICollection<Page> ForbiddenPages { get; set; }
}
现在我的方法是这样的:

    public async Task<JsonNetResult> Get()
    {
        try
        {
            using (var service = new UserService(new CompanyService()))
            {
                var u = from user in await service.GetAll()
                        select new
                        {
                            Id = user.Id,
                            UserName = user.UserName,
                            Email = user.Email,
                            IsApproved = user.IsApproved,
                            IsLockedOut = user.IsLockedOut,
                            MemberOf = user.MemberOf
                        };

                return new JsonNetResult { Data = new { success = true, users = u } }; // Return our users
            }
        }
        catch (Exception ex)
        {
            return new JsonNetResult { Data = new { success = false, error = ex.Message } };
        }
    }
公共异步任务Get() { 尝试 { 使用(var service=new UserService(new CompanyService())) { var u=来自wait service.GetAll()中的用户 选择新的 { Id=user.Id, UserName=user.UserName, Email=user.Email, IsApproved=user.IsApproved, IsLockedOut=user.IsLockedOut, MemberOf=user.MemberOf }; return new JsonNetResult{Data=new{success=true,users=u};//返回我们的用户 } } 捕获(例外情况除外) { 返回新的JsonNetResult{Data=new{success=false,error=ex.Message}; } } 当我运行这个程序时,我得到了和以前一样的错误,但是它显示了更多的细节。它实际上表明:

Newtonsoft.Json.Json.JsonSerializationException类型的异常在Newtonsoft.Json.dll中发生,但未在用户代码中处理

其他信息:检测到类型为“System.Data.Entity.DynamicProxies.Asset_AED71699FAD0007BF6F823A5F022DB9888F62EBBD9E422BBB11D7A191CD784288”的自引用循环。路径“用户[0]。成员[0]。公司。资产[0]。类别[0]。资产”


现在我将检查是否可以更改递归限制:(

您可以尝试添加[DataContract(IsReference=true)]这将使用引用ID序列化对象,并应解决循环引用问题。

根据您的更新,我将假设递归限制的当前值是问题所在。该属性的文档相对稀疏,但可以在此处找到

我相信您可以通过以下代码行替换当前的返回行来解决问题

JsonResult retVal = new JsonResult();
retVal.RecursionLimit = 1000; //maybe parameteraize this?
reVal.Data = = new { success = true, users = u };
return retVal;
编辑:更新后,我知道解决问题有多容易,因为现在由
JsonConvert.SerializeObject引发异常,我以前解决过:)

根据您的更新,您可以通过更改
executesult
中的一些代码来轻松解决这个问题(我对这个选项更有信心,因为我在当前项目中实际实现了它,我个人没有使用
JsonResult
类,我之前的建议只是利用我对json.NET的一般知识)。您可以像下面的示例一样调用
SerializeObject
重载,当您有循环引用时,它现在将抛出

string json = JsonConvert.SerializeObject(YourInstanceToSerialize, Formatting.Indented,
 new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize });

ReferenceLoopHandling
的可用值可在此处找到;我相信默认值是0,这就是代码抛出的原因。由于您已经使用了这些更改进行了更新,我想我建议使用第二种方法(至少我知道它会起作用),但也可以尝试第一种方法。

我发现关闭这些查询的延迟加载是有效的。如果需要,只需确保您的查询通过“包含”选择所有需要的内容。 然后在查询之前:

efContext.Configuration.LazyLoadingEnabled = false;

您确定它不是来自
JsonResult
类吗?我自己还没有使用过,但是json.NET有一个标志,表明是否允许循环引用,默认情况下我认为不允许
JsonResult
有一个名为
RecursionLimit
的属性,它很可能是同一个属性(具有循环引用的结构本质上是递归的),可能该值设置为null或0?我如何检查它是否来自JsonResult类?当我使用fiddler时,它指出问题来自System.Web.Script.Serialization.JavaScriptSerializer.SerializeValueInternal,这表明可能是JsonResult,因为其他所有内容都使用JSON.Net?很抱歉,响应延迟太久。我给出了一个应该能解决你问题的答案:)你找到正确的解决方法了吗?如果发现,请更新这个问题,让我知道它。
JsonResult retVal = new JsonResult();
retVal.RecursionLimit = 1000; //maybe parameteraize this?
reVal.Data = = new { success = true, users = u };
return retVal;
string json = JsonConvert.SerializeObject(YourInstanceToSerialize, Formatting.Indented,
 new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Serialize });
efContext.Configuration.LazyLoadingEnabled = false;