C# c ASP.Net内核和Linq:聚合函数MIN和MAX

C# c ASP.Net内核和Linq:聚合函数MIN和MAX,c#,linq,asp.net-core,C#,Linq,Asp.net Core,Visual Studio 2019;ASP.NETCore2.1 我有一个数据库系统,它有一个在各种机器上发生的事件表 // 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 dat

Visual Studio 2019;ASP.NETCore2.1

我有一个数据库系统,它有一个在各种机器上发生的事件表

// 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,
)
我想检索特定机器的最早和最新事件日期。在SSMS中,我可以通过以下方式获得我想要的信息:

SELECT
       MIN([eventDate]),
       MAX([eventDate])
FROM eventLog
WHERE UPPER(machineName) LIKE 'MY-MACHINENAME%';
在示例运行中,我得到的最小/最大值为:

2015-08-17 10:31:47.000 / 2019-05-02 12:54:20.000
注意:machineName可以是像mypc这样的简单字符串,也可以是FQDN mypc.company.com。我分割出可能的FQDN的第一个虚线部分,并将其与已删除任何虚线部分的myMachine变量进行比较

在C语言中,我知道有聚合方法,但我很难遵循我找到的文档和示例,并将它们转化为实际实践。到目前为止,我已经:

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();
这会运行,但不会为最小值提供有用的结果。这大约是11年前的事了

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

如何将SSMS查询转换为LINQ查询?

您可以尝试执行以下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();

您可以尝试以下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();

我做了一个快速的烟雾测试,你的选择对我有用。为什么不调用range.Min和range.Max来从过滤后的数据集中获取结果

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();

我做了一个快速的烟雾测试,你的选择对我有用。为什么不调用range.Min和range.Max来从过滤后的数据集中获取结果

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();
您可以尝试以下方式:-

        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);
        }
您可以尝试以下方式:-

        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);
        }
在ctx.OrderBy中。。。有人告诉我不能将ctx类型转换为DateTime。找不到强制的方法在ctx.OrderBy中。。。有人告诉我不能将ctx类型转换为DateTime。没办法强迫你这么做。