0
votes

c # ASP.Net Core et Linq: fonctions d'agrégation MIN et MAX

Visual Studio 2019; ASP.Net Core 2.1

J'ai un système de base de données qui a un tableau des événements qui se produisent sur différentes machines.

8/2/2004 8:05:27 PM  /  5/2/2019 12:00:00 AM  

Je veux récupérer l'événement le plus ancien et le plus récent dates pour une machine particulière. Dans SSMS, je peux obtenir les informations que je veux avec:

public class VisibleRange {
    public DateTime start { get; set; }
    public DateTime end { get; set; }
}

...

var ctx = userTrackingContext.EventLog;

usertrackingRange = (
    from eventLog in userTrackingContext.EventLog
    where eventLog.Machine.ToUpper().Split(
        '.',
        StringSplitOptions.RemoveEmptyEntries
    )[0].Trim().Equals(myMachine)
    select eventLog.Date
).Select(range => new VisibleRange {
    start = ctx.Min(a => a.Date),
    end = ctx.Max(a => a.Date)
}).First();

Dans un exemple d'exécution, j'obtiens des valeurs min / max de:

2015-08-17 10:31:47.000 / 2019-05-02 12:54:20.000

Remarque: machineName peut être une chaîne "simple" comme "mypc" ou un FQDN ("mypc.company.com"). J'ai divisé le premier segment "pointillé" du FQDN possible et je le compare à la variable myMachine qui a déjà eu des parties pointillées supprimées.

En C #, je suis conscient qu'il y a sont des méthodes agrégées mais j'ai du mal à suivre les documents et les exemples que j'ai trouvés et à les traduire dans la pratique réelle. J'ai jusqu'à présent:

SELECT
       MIN([eventDate]),
       MAX([eventDate])
FROM eventLog
WHERE UPPER(machineName) LIKE 'MY-MACHINENAME%';

Cela fonctionne mais ne me donne pas de résultats utiles pour la valeur Min. Ce délai est d'environ 11 ans.

// pseudo code
eventLog (
    id int primary key not null,
    eventType varchar(16) not null,
    machineName varchar(64) not null,
    loggedInUser varchar(16) not null,
    eventDate datetime not null,
)

Comment puis-je convertir la requête SSMS en requête LINQ?


0 commentaires

3 Réponses :


0
votes

Vous pouvez essayer de suivre la requête LINQ

usertrackingRange = (
from eventLog in userTrackingContext.EventLog
where eventLog.Machine.ToUpper().Split(
    '.',
    StringSplitOptions.RemoveEmptyEntries
)[0].Trim().Equals(myMachine)
select eventLog.Date
).Select(range => new VisibleRange {
   start = ctx.OrderByAscending(a => a.Date).First(),
   end = ctx.OrderByDescending(a => a.Date).First()
}).First();


1 commentaires

Dans les lignes ctx.OrderBy ... , on me dit que je ne peux pas convertir du type ctx en DateHeure . Je ne vois pas de moyen de contraindre cela.



0
votes

J'ai fait un test de fumée rapide et vos sélections fonctionnent pour moi. Pourquoi n'appelez-vous pas range.Min et range.Max pour obtenir les résultats de votre ensemble de données filtré?

var now = DateTime.Now;

var nums = new List<Num>
{
    new Num { Min = now, Max = now.AddDays(1) },
    new Num { Min = now.AddDays(10), Max = now.AddDays(50) },
    new Num { Min = now.AddDays(51), Max = now.AddDays(100) },
};

var minMaxNum = nums.Select(num => new Num
{
    Min = nums.Min(_ => _.Min),
    Max = nums.Max(_ => _.Max),
}).First();


0 commentaires

2
votes

Vous pouvez essayer comme: -

        var range = new VisibleRange() { };

        var matched = userTrackingContext.EventLog.Where(a => a.MachineName.StartsWith(myMachine));

        if(matched != null)
        {
            range.start = matched.Min(a => a.EventDate);
            range.end = matched.Max(a => a.EventDate);
        }


0 commentaires