2017-02-22 4 views
1

Ich verwende Entity Framework Core nach Chris Sakells Blog here.Entity Framework Core - Problem beim Laden verwandter Entitäten, die auch verwandte Entitäten enthalten

Er verwendet Generics, um seine Repositories zu verwalten und auch ein Basis-Repository, das er für alle anderen Repositories verwendet.

Ein Teil des Basisrepositorys enthält den folgenden Code zum Abrufen einer einzelnen Entität, die auch verwandte Entitäten mithilfe der Option includeProperties herunterlädt. Hier ist der generische Code zum Abrufen eines einzelnen Artikels.

public T GetSingle(Expression<Func<T, bool>> predicate, params Expression<Func<T, object>>[] includeProperties) 
{ 
    IQueryable<T> query = _context.Set<T>(); 

    foreach (var includeProperty in includeProperties) 
    { 
     query = query.Include(includeProperty); 
    } 

    return query.Where(predicate).FirstOrDefault(); 
} 

Ich benutze es auf einer Client-Tabelle, die viele Jobs damit verbunden hat.

So habe ich meinen Code strukturiert.

public ClientDetailsViewModel GetClientDetails(int id) 
    { 
     Client _client = _clientRepository 
      .GetSingle(c => c.Id == id, c => c.Creator, c => c.Jobs, c => c.State); 

     if(_client != null) 
     { 
      ClientDetailsViewModel _clientDetailsVM = mapClientDetailsToVM(_client); 
      return _clientDetailsVM; 
     } 
     else 
     { 
      return null; 
     } 
    } 

Die Linie:

.GetSingle(c => c.Id == id, c => c.Creator, c => c.Jobs, c => c.State); 

ruft erfolgreich Werte für Schöpfer Zustand und Job.

Es wird jedoch nichts für die verbundenen Entitäten abgerufen, die den "Jobs" zugeordnet sind.

enter image description here

In particuar, JobVisits ist eine Sammlung von Abfragen Arbeitsplätze.

Der Vollständigkeit Ich füge den „Job“ und „jobvisit“ Entitäten unter

public class Job : IEntityBase 
{ 
    public int Id { get; set; } 

    public int? ClientId { get; set; } 
    public Client Client { get; set; } 

    public int? JobVisitId { get; set; } 
    public ICollection<JobVisit> JobVisits { get; set; } 

    public int? JobTypeId { get; set; } 
    public JobType JobType { get; set; } 

    public int? WarrantyStatusId { get; set; } 
    public WarrantyStatus WarrantyStatus { get; set; } 

    public int? StatusId { get; set; } 
    public Status Status { get; set; } 

    public int? BrandId { get; set; } 
    public Brand Brand { get; set; } 

    public int CreatorId { get; set; } 
    public User Creator { get; set; } 

    .... 
} 

public class JobVisit : IEntityBase 
{ 
    ... 
    public int? JobId { get; set; } 
    public Job Job { get; set; } 

    public int? JobVisitTypeId { get; set; } 
    public JobVisitType VisitType { get; set; } 
} 

Meine Frage ist, wie ändere ich das Repository Code oben und meine GetSingle Gebrauch, so dass ich auch die zugehörige laden enitities JobVisit Sammlung und die anderen verwandten Einzeleinheiten Brand und JobType?

Antwort

1

Es ist nicht erforderlich, dass die Navigationseigenschaften für die zugeordneten "Jobs" abgerufen werden. Aus diesem Grund sind einige Eigenschaften null. Standardmäßig geht der .Include(property); nur 1-Level tief und das ist eine gute Sache. Es verhindert, dass Ihre Abfrage alle Daten Ihrer Datenbank abruft. Wenn Sie mehrere Ebenen einschließen möchten, sollten Sie .ThenInclude(property) nach .Include(property) verwenden. Von den documentation:

using (var context = new BloggingContext()) 
{ 
    var blogs = context.Blogs 
     .Include(blog => blog.Posts) 
      .ThenInclude(post => post.Author) 
     .ToList(); 
} 

Mein Rat ist, dass Ihre Methode public T GetSingle(...) schön und ich würde es nicht um tiefere Ebene einzubeziehen ändern. Stattdessen können Sie einfach explizites Laden verwenden. Aus der documentation:

using (var context = new BloggingContext()) 
{ 
    var blog = context.Blogs 
     .Single(b => b.BlogId == 1); 

    context.Entry(blog) 
     .Collection(b => b.Posts) 
     .Load(); 

    context.Entry(blog) 
     .Reference(b => b.Owner) 
     .Load(); 
} 
Verwandte Themen