繁体   English   中英

使用Lambda,Linq,Entity Framework选择值的更改

[英]Selecting changes in values with Lambda, Linq, Entity Framework

我有以下Entity Framework类定义:

class TimeValue
{
    DateTime StartDate;
    double Value;
}

假设给出以下一系列值,我只想知道值何时更改:

2000-01-01  100
2000-01-15  100
2000-02-01  110
2000-02-15  120
2000-03-01  120
2000-03-15  50
2000-04-01  50
2000-04-15  50
2000-05-01  120

结果将是:

2000-01-01  100
2000-02-01  110
2000-02-15  120
2000-03-15  50
2000-05-01  120

我可以使用lambda / linq选择合适的值。 然后我使用以下代码迭代结果以添加到列表:

var timeValueQuery = _context.TimeValues.Where(...);

List<TimeValue> timeChanges = new List<TimeValue>();
TimeValue lastValue = null;
foreach (var tvq in timeValueQuery)
{
    if (lastValue == null || tvq.Value != lastValue.Value)
    {
        timeChanges.Add(tvq);
    }
    lastValue = tvq;
}

只是想知道是否有更快/更好的方法来做到这一点。

您可以创建仅在满足某些条件时才返回项目的扩展方法。 这个条件(谓词)将接受两个参数 - 上一个和当前项,它应该比较:

public static IEnumerable<T> TakeIf<T>(this IEnumerable<T> source, 
                                       Func<T, T, bool> predicate)
{
    var enumerator = source.GetEnumerator();
    if (!enumerator.MoveNext())
        yield break;

    yield return enumerator.Current;
    T previous = enumerator.Current;

    while (enumerator.MoveNext())
    {
        T current = enumerator.Current;
        if (predicate(previous, current))
            yield return current;

        previous = current;
    }
}

传递谓词,检查先前和当前项目是否具有不同的值。 用法:

var timeChanges = _context.TimeValues.TakeIf((x, y) => x.Value != y.Value);

在再次读取数据集后编辑。

我看到分组不起作用。 理想情况下,由于网络io等原因,您希望在数据库服务器上使用此逻辑,而不是客户端。

您可以将其写为proc或动态sql。 动态sql在短期内可能更容易。

简单的方法,选择它进入游标。 循环到临时表变量并返回结果集。

如果您的数据集非常小,那么请坚持使用易读的linq循环。 除非您需要,否则不要增加复杂性。 即不要微观优化。

不知道这是不是更好:)反正:

  IQueryable<TimeValue> values = ...; // initialize here
  var query = from v in values
              where (from v2 in values
                     orderby v2.StartDate
                     where v2.StartDate > v.StartDate
                     select v2.Value).FirstOrDefault() != v.Value
              select v;

如果可以为零,则将FirstOrDefault()更改为FirstOrDefault(impossible_value)。 对于循环也可能更有效(但你要求LINQ)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM