【问题标题】:LINQ Select Last & Unique Record from a DB using ListLINQ 使用列表从数据库中选择最后一个唯一记录
【发布时间】:2016-08-23 08:47:25
【问题描述】:

我有一张所有车辆都已注册的表格,还有一张表格,其中每辆注册的车辆都有数百万次 ping。

我正在尝试使用 LINQ QUERY 从过去 30 分钟内发送 ping 的每辆车中选择最后一个 ping。我已经通过“for each”的想法完成了下面的代码,但我不确定这是否是最好的方法。

我想知道是否有更好的方法来使用单行来选择它?我知道我可以通过 vehicle_fleetNumber 对它们进行“分组”,但由于 TAKE() 限制了最终结果,因此我无法获得正确的结果。

var timeRestriction = DateTime.UtcNow.AddMinutes(-30);
var x = _db.Vehicles.Where(r=> r.isActive.Equals(true) && r.helperLastPing > timeRestriction);

foreach (var vehicle in x)
{
    var firstOrDefault = _db.Tracks.OrderByDescending(r => r.collectedOn)
        .FirstOrDefault(r => r.vehicle_fleetNumber.Equals(vehicle.fleetNumber));
}

return View();

谢谢,

【问题讨论】:

    标签: c# sql-server asp.net-mvc linq


    【解决方案1】:

    是的,您应该在数据库中通过连接两个表并使用GroupBy

    var query = from v in _db.Vehicles
                join t in _db.Tracks
                on v.fleetNumber equals t.vehicle_fleetNumber
                where v.isActive && v.helperLastPing > timeRestriction
                group t by t.vehicle_fleetNumber into vehicleGroup
                select vehicleGroup.OrderByDescending(x => x.collectedOn).First();
    
    foreach(var track in query)
    {
        // ...
    }
    

    你也可以用query.ToArrayToList代替foreach,我不知道你想用它做什么。

    【讨论】:

    • 嗨@Tim Schmelter。谢谢您的帮助。如果您看到图像 postimg.org/image/pc3agbm75,则 LINQ 会选择整个数据库,然后应用过滤器。这大约需要 7 秒,这是因为我目前只有 63884 行。使用 for each 需要 1 秒来选择整个数据。无论如何只能为每个选择最后一个 ping 吗?
    【解决方案2】:

    如果你从 nuget 获得 moreLinq,你会发现 .maxby() 方法: 例如在不同的上下文中:

    //get the correct exchange rate
    var rateList = _db.lists_ExchangeRates.Where(
               rates => rates.Currency == currencyCode);
               Decimal? exRate = rateList.MaxBy(rates => rates.LastUpdated).ExchangeRate;
    

    另见下文,这提供了更多信息。

    MoreLinq maxBy vs LINQ max + where

    【讨论】:

    • 我已经尝试过了,但我得到了 System.OutOfMemoryException 异常,因为它可能正在读取超过 65k 行的整个表。见下方代码var query = _db.Tracks.Where(r => r.Vehicle.isActive && r.Vehicle.helperLastPing > timeRestriction); var maxBy = query.MaxBy(track => track.vehicle_fleetNumber);谢谢你的帮助
    • 您可以通过在 SQL 服务器端引入一个视图并对其进行查询来限制您的结果。它应该使处理数据变得更快、更容易。
    【解决方案3】:

    在我的情况下,如果我想要最后保存的数据,我使用此方法

    var id = db.DPSlips.Max(item => item.Id);

    所以我认为这可能会像尝试一样工作

    var timeRestriction = DateTime.UtcNow.AddMinutes(-30); var x = _db.Vehicles.Max(a => a.isActive == true && a.helperLastPing > timeRestriction);

    【讨论】:

    • Thanks mate 它只会选择车辆信息,车辆和ping有不同的表。 helperLastPing 列在车辆表中包含最后的 ping 信息,因为它可以帮助我在不选择 Tracks 表的情况下进行其他检查,但所有 ping 信息都在 Track 表中。假设我在 Vehicle Table 中有车辆 1、2 和 3。对于每辆车,Track 表可能有 100 万次或更多 ping。我要做的是选择最后一辆车的 ping 而不选择所有内容,因为轨道表会很大。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多