entity framework核心.Include()问题

一直在玩ef核心,并且在include语句中遇到了问题。 对于这个代码我得到2家公司,这是我所期望的。

public IEnumerable GetAllCompanies(HsDbContext db) { var c = db.Company; return c; } 

这回来了

 [{"id":1,"companyName":"new","admins":null,"employees":null,"courses":null}, {"id":2,"companyName":"Test Company","admins":null,"employees":null,"courses":null}] 

正如你所看到的,有两家公司,所有相关的属性都是null,因为我曾经使用任何包含,这是我所期望的。 现在当我将方法更新为:

 public IEnumerable GetAllCompanies(HsDbContext db) { var c = db.Company .Include(t => t.Employees) .Include(t => t.Admins) .ToList(); return c; } 

这就是它的回报:

 [{"id":1,"companyName":"new", "admins":[{"id":2,"forename":"User","surname":"1","companyId":1}] }] 

它只返回一家公司,只包括管理员。 为什么不包括2家公司及其员工?

 public class Company { public int Id { get; set; } public string CompanyName { get; set; } public List Admins { get; set; } public List Employees { get; set; } public List Courses { get; set; } public string GetFullName() { return CompanyName; } } public class Employee { public int Id { get; set; } public string Forename { get; set; } public string Surname { get; set; } public int CompanyId { get; set; } [ForeignKey("CompanyId")] public Company company { get; set; } public ICollection Employeecourses { get; set; } } public class Admin { public int Id { get; set; } public string Forename { get; set; } public string Surname { get; set; } public int CompanyId { get; set; } [ForeignKey("CompanyId")] public Company Company { get; set; } } 

我不确定你是否已经看到了这个问题的公认答案,但问题在于JSON Serializer如何处理循环引用。 有关更多参考资料的完整详细信息和链接可以在上面的链接中找到,我建议深入研究这些内容,但简而言之,将以下内容添加到startup.cs将配置序列化程序以忽略循环引用:

 services.AddMvc() .AddJsonOptions(options => { options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; }); 

我测试你的代码,我的测试中存在这个问题。 在这篇文章中LINK建议使用数据投影。 对于你的问题如下所示,是工作。

 [HttpGet] public dynamic Get() { var dbContext = new ApplicationContext(); var result = dbContext.Companies .Select(e => new { e.CompanyName, e.Id, e.Employees, e.Admins }) .ToList(); return result; } 

EF Core无法进行延迟加载。 请参考这里 。

或者,您可以使用预先加载。

阅读这篇文章

下面是我为实现预先加载而创建的扩展方法。

扩展方法:

 public static IQueryable IncludeMultiple( this IQueryable source, List>> navigationPropertyPath) where TEntity : class { foreach (var navExpression in navigationPropertyPath) { source= source.Include(navExpression); } return source.AsQueryable(); } 

存储库调用:

 public async Task FindOne(ISpecification spec) { return await Task.Run(() => Context.Set().AsQueryable().IncludeMultiple(spec.IncludeExpression()).Where(spec.IsSatisfiedBy).FirstOrDefault()); } 

用法:

 List nestedObjects = new List {new Rules()}; ISpecification blogSpec = new BlogSpec(blogId, nestedObjects); var challenge = await this._blogRepository.FindOne(blogSpec); 

依赖关系:

 public class BlogSpec : SpecificationBase { readonly int _blogId; private readonly List _nestedObjects; public ChallengeSpec(int blogid, List nestedObjects) { this._blogId = blogid; _nestedObjects = nestedObjects; } public override Expression> SpecExpression { get { return blogSpec => blogSpec.Id == this._blogId; } } public override List>> IncludeExpression() { List>> tobeIncluded = new List>>(); if (_nestedObjects != null) foreach (var nestedObject in _nestedObjects) { if (nestedObject is Rules) { Expression> expr = blog => blog.Rules; tobeIncluded.Add(expr); } } return tobeIncluded; } 

如果它有帮助会很高兴。 请注意,这不是生产就绪代码。