簡體   English   中英

有沒有更優雅的解決方案來計算在Entity Framework中正在發生某個值的Timespan?

[英]Is there a more elegant solution to calculating the Timespan that a certain value is occurring in Entity Framework?

我的問題:我的數據庫中有一個名為DevicePropertyUpdates的表。 我們使用此表記錄設備中的狀態更改。 我需要知道特定模式在指定時間范圍內處於活動狀態的總時間。

例如,如果模式A從00:00到4:00,模式B從4:00到10:00,模式A從10:00到16:00,模式C從16:00到24:00 。 如果我想知道模式A在一天中處於激活狀態的時間,我將00:00到4:00和10:00到16:00加起來,總共得到10個小時。

我當前的代碼如下。 非常迭代,我相信它將迫使實體框架在整個日期范圍內實現所有這些模式。 我正在尋找一種更優雅的解決方案,以提高我的問題解決能力並編寫更簡潔的代碼。 我希望我只是想念一些可以學到的東西。 我考慮的想法是.Zip,.GroupBy或某種聯接來發現差異,但是我想不出任何有用的方法。

架構師更喜歡使用實體框架方法。 DevicePropertyUpdates表具有以下結構。

時間戳記-日期時間

StringValue-varchar(最大值)

名稱-varchar(100)

示例SQL

第1行:“ OperatingMode”,“ A”,“ 2014/7/1 1:00:00”

第2行:“ OperatingMode”,“ A”,“ 2014/7/1 2:00:00”

第3行:“ OperatingMode”,“ B”,“ 2014年7月1日2:15:00”

第4行:“ OperatingMode”,“ A”,“ 2014年7月1日3:33:00”

using (Container container = ContextFactory.CreateInstance())
{
    IEnumerable<Model.DevicePropertyUpdate> updates =
        container.DevicePropertyUpdates.Where(
            dpu => dpu.Name == "OperatingMode" && dpu.Timestamp <= endTime && dpu.Timestamp >= startTime);

    TimeSpan totalTime = TimeSpan.Zero;
    DateTime? start = null;

    foreach (var update in updates)
    {
        if (update.StringValue == operatingMode)
        {
            if (!start.HasValue)
            {
                start = update.Timestamp;
            }
        }
        else
        {
            if (start.HasValue)
            {
                totalTime += update.Timestamp - startTime;
                start = null;
            }
        }
    }
    //Include edge case if matching operating mode was the last to occur in the time range.
    if (start.HasValue)
    {
        totalTime += endTime - startTime;
    }

    return totalTime;
}

您可以總結從時間戳到結束時間的所有“打開時間”。 然后將所有空閑時間相加並求和。 這將需要兩個SQL語句和一個遵循一些規則的結果集。 它必須以ON開頭,以IDLE結尾,每個ON必須有一個對應的IDLE。

|    ON     IDLE      ON     IDLE             ON       IDLE            |
     ------------------------------------------------------------------
                      -------------------------------------------------
                                              -------------------------


             ----------------------------------------------------------
                             ------------------------------------------
                                                       ---------------- 

您的Linq看起來像這樣。

using (var db = new TestContext()) {
    DateTime startDate = new DateTime(2014,05,01), endDate = new DateTime(2014,06,1);

    var baseQuery = db.DevicePropertyUpdates
                        .Where(p => p.TimeStamp >= startDate && p.TimeStamp < endDate)
                        .Where(p => p.Name == "OperatingMode");

    var OnSum = baseQuery.Where(p => p.StringValue == "ON")
                       .Sum(p => SqlFunctions.DateDiff("ss",p.TimeStamp, endDate));
    var IdleSum = baseQuery.Where(p => p.StringValue == "IDLE")
                       .Sum(p => SqlFunctions.DateDiff("ss", p.TimeStamp,endDate));

    var duration = TimeSpan.FromSeconds(OnSum.Value - IdleSum.Value);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM