2017-10-13 2 views
0

J'ai ce modèle:EF de base Include() n'interroge pas tous Childs

public class RepairRequest 
{ 
    [Key] 
    public int Id { get; set; } 
    public List<RepairAction> RepairActions { get; set; } 
    public decimal TotalPrice => RepairActions.Sum(r => r.ActionPrice); 
    public string LastOperation => RepairActions.LastOrDefault().RepairOperation.Description; 
} 

public class RepairAction 
{ 
    [Key] 
    public int Id { get; set; } 
    public int RepairRequestId { get; set; } 
    public RepairRequest RepairRequest { get; set; } 
    public int RepairOperationId { get; set; } 
    public RepairOperation RepairOperation { get; set; } 
    public decimal ActionPrice { get; set; } 
} 

public class RepairOperation 
{ 
    [Key] 
    public int Id { get; set; } 
    public string Description { get; set; } 
} 

J'essaie d'interroger RepairRequests et obtenir TotalPrice et aussi LastOperation dans une liste, mais ne fonctionne pas pour les deux propriétés . C'est ce que j'ai essayé jusqu'à maintenant:

using (var context = new ServiceManagerContext(new DbContextOptions<ServiceManagerContext>())) { 
    var data = context.RepairRequests 
     .Include(r => r.RepairActions).ThenInclude(r => r.RepairOperation); // Only LastAction works 
     //.Include("RepairActions").Include("RepairActions.RepairOperation"); // Only LastAction works 
     //.Include(r => r.RepairActions); // Only TotalPrice works 
     //.Include("RepairActions"); // Only TotalPrice works 

    var repairRequest = data.FirstOrDefault(r => r.Id == 5); 
    Assert.NotNull(repairRequest); 
    Assert.Equal(60.0m, repairRequest.RepairPrice); 
    Assert.Equal("Παραδόθηκε", repairRequest.LastAction); 
} 

Merci.

+0

'LastAction' ou' LastOperation'? vous les confondez – GGO

+0

LastOperation. Pardon. – dseferlis

+0

Veuillez toujours indiquer clairement la version que vous utilisez. Esp. ef-core s'est développé rapidement par le passé. –

Répondre

1

Je considérerais éviter d'essayer pour résoudre les propriétés calculées dans vos entités de domaine et chercher plutôt à les résoudre lors de l'interrogation des données pour remplir les modèles de vue.

Si votre modèle de vue a besoin du TotalPrice et LastOperation, puis fourni un dépôt ou tel retour IQueryable vous pouvez étendre la requête pour renvoyer ce qui est nécessaire exécution différée plutôt que d'essayer de compter sur désireux de charger l'ensemble de l'arbre:

Ie

IQueryable<RepairRequest> requests = context.RepairRequests.Where(x => x.Id == 5); // Or pull from a Repository returning the IQueryable 
var viewModelData = requests.Select(x => new {x.Id, TotalPrice = x.RepairActions.Sum(), LastOperation = x.RepairActions.LastOrDefault()?.RepairOperation?.Description }).SingleOrDefault(); 

Cela devrait exécuter une requête plus optimisée et vous retourner un type anonyme avec uniquement les données dont vous avez besoin pour remplir tout modèle de vue que vous souhaitez afficher. Le bit iffy contourne les situations où il n'y a pas d'actions de réparation, ou une action de réparation sans opération. EF doit éviter l'attribut null ref et retourner simplement null. la ?. La syntaxe n'est peut-être pas nécessaire ou prise en charge. Il se peut donc qu'elle doive simplement être ".". Si vous utilisez une méthode où vous souhaitez charger ou ignorer ces entités et exécuter Linq à partir des instances d'entité, faites attention à .SingleOrDefault() et explorez les champs enfants.

1

Firstaball vous devez déclarer clés étrangères, et le drapeau propriétés virtuelles comme:

public class RepairRequest 
{ 
    [Key] 
    public int Id { get; set; } 
    public virtual ICollection<RepairAction> RepairActions { get; set; } 
    public decimal TotalPrice => RepairActions.Sum(r => r.ActionPrice); 
    public string LastOperation => RepairActions.LastOrDefault().RepairOperation.Description; 
} 

public class RepairAction 
{ 
    [Key] 
    public int Id { get; set; } 
    public decimal ActionPrice { get; set; } 

    public int RepairRequestId { get; set; } 
    [ForeignKey("RepairRequestId ")] 
    public virtual RepairRequest RepairRequest { get; set; } 

    public int RepairOperationId { get; set; } 
    [ForeignKey("RepairOperationId")] 
    public RepairOperation RepairOperation { get; set; } 
} 

Ensuite, vous pouvez appeler ce qui charge toutes les valeurs des enfants:

var data = context.RepairRequests.Include("RepairActions.RepairOperation");