2016-07-24 110 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; 
     } 

如果有幫助,會很高興。請注意,這不是生產就緒代碼。