J'ai un grand tableau dans lequel j'essaie de sélectionner la ligne 1
pour chaque FK dans une liste.
Mon tableau se présente comme suit:
[ { AssetId: 1, Timestamp: 3478 }, { AssetId: 2, Timestamp: 1092 }, { AssetId: 3, Timestamp: 344 } ]
Où ChangeId
est mon PK
, AssetId
est mon FK
et L'horodatage
est la valeur que j'essaie de sélectionner.
Si j'essaye ce qui suit:
var results = from Asset in _context.Asset join change in _context.Change on Asset.AssetId equals change.AssetId into potentialChange from actualChange in potentialChange.OrderByDescending(y => y.ChangeId).Take(1) select { AssetId, Timestamp }
Où mon résultat attendu serait:
ChangeId | AssetId | Timestamp 1 1 123 2 2 999 3 1 3478 4 3 344 5 2 1092
Cette requête marque le L'expression LINQ n'a pas pu être traduite et sera évaluée localement.
qui ne convient pas pour un déploiement en production.
Lancer une boucle foreach
et sélectionner chaque élément 1 par 1 fonctionne, ce n'est pas une solution performante.
Y a-t-il un moyen approprié pour atteindre ce qui précède ?
3 Réponses :
Essayez d'utiliser .First ()
au lieu de .Take(1)
LINQ Comment prendre un enregistrement et sauter le reste c #
Déclenche un échec de l'inférence Type lors de l'appel à l'exception SelectMany
Utilisez Group By
comme suit:
List<MyTable> data = new List<MyTable>() { new MyTable(){ChangeId = 1, AssetId = 1, Timestamp = 123}, new MyTable(){ChangeId = 2, AssetId = 2, Timestamp = 999}, new MyTable(){ChangeId = 3, AssetId = 1, Timestamp = 123}, new MyTable(){ChangeId = 5, AssetId = 3, Timestamp = 123}, new MyTable(){ChangeId = 5, AssetId = 2, Timestamp = 123}, }; var expectedData = data.OrderByDescending(d => d.Timestamp).GroupBy(d => d.AssetId).Select(g => new { AssetId = g.Key, TimeStamp = g.First().Timestamp }).ToList();
Cela donnera le résultat attendu.
Essayez de le regrouper par AssetId et prenez le maximum de chaque groupe
var results = from Asset in _context.Asset join change in _context.Change on Asset.AssetId equals change.AssetId into potentialChange group potentialChange by potentialCharge.AssetId into g select { g.Key, g.Max().Timestamp }
Désolé, je vais le supprimer
Pas de soucis! (Peut-être devriez-vous avoir?) Ou .
Au lieu de joindre, ajoutez des propriétés de navigation sur les entités et utilisez quelque chose comme
_context.Assets.SelectMany (asset => asset.Changes.Take (1)). Sel ect (change => new {chan ge.Timestamp , changez. AssetId})