2017-10-11 13 views
0

J'ai 2 tables _customerRepository.GetAllQueryable() et _customerSettlementRepository.GetAllQueryable().Utiliser linq dans la clause where

Dans la table _customerSettlementRepository.GetAllQueryable(), j'ai la colonne ApplyD (date), après avoir joint ces deux ensemble, je veux trouver max ApplyD dans la clause where. Ceci est mon code:

var settlements = from c in _customerRepository.GetAllQueryable() 
    join cs in _customerSettlementRepository.GetAllQueryable() on new {c.CustomerMainC, c.CustomerSubC} 
    equals new {cs.CustomerMainC, cs.CustomerSubC} into c1 
    where cs.ApplyD == (c1.Select(b=>b.ApplyD).Max()) 
    select new CustomerSettlementViewModel() 
    { 
      TaxRate = cs.TaxRate 
    }; 
+1

ajouter l'entrée et la sortie par exemple – Backs

+0

Question est pas très clair, waht voulez-vous exactement? – GGO

+0

Simplifiez votre requête. Si la requête LINQ semble moche, le SQL généré et les performances seront * également * moche. Vous ne pourrez pas non plus maintenir ce code dans le futur. –

Répondre

2

Il est remarquable que très souvent dans ces questions que les gens viennent avec une déclaration SQL (-comme) sans spécification de l'objectif qu'ils veulent atteindre. Il est donc impossible de voir si la déclaration fournie répond aux exigences.

Quoi qu'il en soit, il semble que vous avez quelque chose comme Customers (en CustomerRepository) et CustomerSettlements dans CustomerSettlementRepository.

les deux Customers et CustomerSettlements ont un CustomerMainC et un CustomerSubC. Vous voulez joindre Customers et CustomerSettlements sur ces deux propriétés.

Un CustomerSettlement a également un ApplyD et un TaxRate.

Vous voulez seulement garder la jointure des résultats où ApplyD a la valeur maximale de ApplyD

Enfin, de tous les restants se joindre résultat que vous voulez créer un objet CustomerSettlementViewModel avec la valeur du TaxRate dans la jointure résultat qui était pris du CustomerSettlement.

Maintenant que j'écris ceci, je me demande pourquoi vous devez vous joindre à la première place, car vous n'utilisez que les valeurs des CustomerSettlements, et non du Client. En outre, si deux clients sont joints avec les mêmes CustomerSettlements. cela entraînera deux objets CustomerSettlementViewModel égaux. Mais supposons que c'est vraiment ce que vous voulez.

Dans les étapes de bébé:

IQueryable<Customer> customers = ... 
IQueryable<CustomerSettlement> customerSettlements = ... 

var joinResults = customers.Join(customerSettlements 
    customer => new {customer.CustomerMainC, customer.CustomerSubC}, 
    settlement => new {settlement.CustomerMainC, settlement.CustomerSubC} 
    (customer, settlement) => new 
    { 
     settlement.ApplyD, 
     settlement.TaxRate, 
     // add other properties from customers and settlements you want in the end result 
    }); 

En mots: prendre tous Customers et tous CustomerSettlements. De chaque Customer créer un objet ayant les valeurs de CustomerMainC du client et CustomerSubC. Faites la même chose de tous les CustomerSettlement. Lorsque ces deux objets sont égaux, créer un nouvel objet, ayant les valeurs de la ApplyD et TaxRate de CustomerSettlement (et d'autres propriétés dont vous avez besoin dans le résultat final)

Notez que cela est encore un IQueryable. Aucune requête n'est encore effectuée. À partir de ce joinResult, vous ne voulez conserver que les objets ayant la valeur de ApplyD qui est égale à la valeur maximale de ApplyD.

This question on StackOverflow is about selecting the records with the max value. L'idée est de regrouper les enregistrements en groupes ayant la même valeur pour ApplyD. Ensuite, ordonnez les groupes en ordre décroissant et prenez le premier groupe.

var groupsWithSameApplyD = joinResults.GroupBy(
    joinedItem => joinedItem.ApplyD, 
    joinedItem => new CustomerSettlementViewModel() 
    { 
     TaxRate = orderedItem.TaxRate, 
     // add other values from joinedItems as needed 
    }); 

Chaque groupe de groupsWithSameApplyD a une clé égale à ApplyD. Le groupe se compose d'objets CustomerSettlementViewModel créés à partir des éléments joints qui ont tous le même ApplyD que celui du Key du groupe.

Maintenant, l'ordre décroissant par:

var orderedGroups = groupsWithSameApplyD.OrderByDescending(group => group.Key); 

Les premiers groupes contient tous les éléments qui ont le plus grand ApplyD. Votre résultat souhaité est la séquence d'éléments dans le groupe.

S'il n'y a aucun groupe, retournez une séquence vide. Notez que si une séquence est demandée en conséquence, il est toujours préférable de retourner une séquence vide au lieu de null, afin que les appelants peuvent utiliser la valeur retournée dans un foreach sans avoir à vérifier null retour

var result = orderedGroups.FirstOrDefault() ?? 
    // if no groups at all, return empty sequence: 
    Enumerable.Empty<CustomerSettlementViewModel>(); 

Note: la FirstOrDefault est la première étape où la requête est réellement effectuée. Si vous le souhaitez, vous pouvez tout mettre dans une grande requête. Je ne sais pas si cela améliorerait la lisibilité et la maintenabilité.

+0

Merci beaucoup Harald Coppoolse, c'est très utile pour moi –

0

enter image description here

Ceci est mon erreur syntet, je dois écrire ce depuis le premier

var settlements = from c in _customerRepository.GetAllQueryable() 
        join cs in _customerSettlementRepository.GetAllQueryable() on new {c.CustomerMainC, c.CustomerSubC} 
         equals new {cs.CustomerMainC, cs.CustomerSubC} 
        select new CustomerSettlementViewModel() 
        { 
         TaxRate = cs.TaxRate 
        }; 
       settlements = settlements.Where(p => p.ApplyD == settlements.Max(b => b.ApplyD));