2016-07-24 109 views
10

一直在玩ef核心,并且对include语句有问题。对于这个代码,我得到了2家公司,这是我的预期。实体框架核心.Include()问题

public IEnumerable<Company> 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}] 

正如你可以看到有2只股票,因为我havnt使用任何包含,这是我所期待的所有相关的属性为null。现在,当我更新的方法是:

public IEnumerable<Company> 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<Admin> Admins { get; set; } 
    public List<Employee> Employees { get; set; } 
    public List<Course> 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<EmployeeCourse> 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; } 
} 
+0

您是否尝试过使用EF 6或更低版本的相同代码? –

+0

你的EF版本是什么? – Mafii

+1

@Mafii,它是EF Core - EF 7,请参阅标题 –

回答

9

我不知道,如果你看过接受的答案这个question,但问题是与JSON序列如何与循环引用涉及的事情。全部细节,并链接到更多的参考资料可以在上面的链接中找到的,我会建议挖掘到这些,但总之,加入以下startup.cs将配置串行忽略循环引用:

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

我不认为这个问题与JSON有任何关系。 – Langdon

+0

我不同意,尽管@JohnMorrison完全可能仅使用JSON作为表达输出的便捷方式。它看起来像一个序列化器引用循环处理问题,但由于使用JSON来显示输出,它可能非常适合这种方式。为什么不让OP在downvoting之前说明是否是这种情况? –

+0

Accutaly这是解决问题的方法。非常感谢! – LaPuyaLoca

1

我测试你的代码,这个问题存在于我的测试中。在这篇文章中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; 
} 
+0

是的,这种方式有效。谢谢。那么你认为它是一个延迟加载实体框架的问题吗? –

+0

当使用包含加载方法是预加载,并在第一个查询中加载数据 –

0

懒惰EF Core尚未加载。 Refer here

或者,您可以使用急切的加载。

阅读本article

下面是扩展方法,我已经建立,实现了预先加载。

扩展方法:

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

库电话:

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

用法:

List<object> nestedObjects = new List<object> {new Rules()}; 

      ISpecification<Blog> blogSpec = new BlogSpec(blogId, nestedObjects); 

      var challenge = await this._blogRepository.FindOne(blogSpec); 

依赖关系:

public class BlogSpec : SpecificationBase<Blog> 
    { 
     readonly int _blogId; 
     private readonly List<object> _nestedObjects; 

     public ChallengeSpec(int blogid, List<object> nestedObjects) 
     { 
      this._blogId = blogid; 
      _nestedObjects = nestedObjects; 
     } 

     public override Expression<Func<Challenge, bool>> SpecExpression 
     { 
      get { return blogSpec => blogSpec.Id == this._blogId; } 
     } 

     public override List<Expression<Func<Blog, object>>> IncludeExpression() 
     { 
      List<Expression<Func<Blog, object>>> tobeIncluded = new List<Expression<Func<Blog, object>>>(); 
      if (_nestedObjects != null) 
       foreach (var nestedObject in _nestedObjects) 
       { 
        if (nestedObject is Rules) 
        { 
         Expression<Func<Blog, object>> expr = blog => blog.Rules; 
         tobeIncluded.Add(expr); 
        } 

       } 

      return tobeIncluded; 
     } 

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