1
votes

Sélectionnez TOP 1 pour chaque FK dans la liste en utilisant Entity Framework

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
  }
]

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 commentaires

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})


3 Réponses :


0
votes

Essayez d'utiliser .First () au lieu de .Take(1)

LINQ Comment prendre un enregistrement et sauter le reste c #


1 commentaires

Déclenche un échec de l'inférence Type lors de l'appel à l'exception SelectMany



1
votes

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.


0 commentaires

1
votes

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
}


0 commentaires