[英]Create custom objects from IQueryable without loading everything into memory
现在,由于这个答案 ,我创建了一个查询,该查询将返回正确的条目。 看到:
IQueryable<Data> onePerHour = dataLastWeek
.Where(d =>
!dataLastWeek
.Any(d2 =>
d2.ArchiveTime.Date == d.ArchiveTime.Date &&
d2.ArchiveTime.Hour == d.ArchiveTime.Hour &&
d2.ArchiveTime < d.ArchiveTime));
现在,为了处理条目并将它们显示在图表上,我只需要模型类Data
一个或两个属性。 用例是这样的:
List<Data> actualData = onePerHour.ToList();
var tempCTupels = new List<TimeTupel<float>>();
tempCTupels.AddRange(actualData.Select(d => new TimeTupel<float>(d.ArchiveTime, d.TempC)));
var co2Tupels = new List<TimeTupel<float>>();
tempCTupels.AddRange(actualData.Select(d => new TimeTupel<float>(d.ArchiveTime, d.CO2Percent)));
TimeTupel
非常简单,定义如下:
public class TimeTupel<TData>
{
public TimeTupel(DateTime time, TData yValue)
{
Time = time;
YValue = yValue;
}
public DateTime Time { get; set; }
public TData YValue { get; set; }
}
当前, actualdata
是一个List<Data>
,这意味着它已完全加载到内存中。
由于我仅使用两个属性,因此无需检索整个对象即可创建TimeTupel
。
现在我的问题是如何实现性能提升? 删除ToList
是正确的方法吗?
只需使用IQueryable<Data>
创建TimeTupel
:
IQueryable<Data> actualData = onePerHour;
产生运行时错误(“ System.InvalidOperationException:'Sql Tree中的Null TypeMapping'”)
使用AsEnumerable
:
IEnumerable<Data> actualData = onePerHour.AsEnumerable();
速度很慢,大约需要22秒才能处理10天的数据
如上面的代码所示,使用ToList
( ToArray
几乎相等):
List<Data> actualData = onePerHour.ToList();
更快,相同数量的数据大约需要5秒
您可以在Select语句中使用匿名类型,以仅将所需的数据列检索到内存中,然后从该处将内存中的数据转换为TimeTupel <>类。 它看起来像这样:
var actualData = dataLastWeek
.Where(d =>
!dataLastWeek
.Any(d2 =>
d2.ArchiveTime.Date == d.ArchiveTime.Date &&
d2.ArchiveTime.Hour == d.ArchiveTime.Hour &&
d2.ArchiveTime < d.ArchiveTime))
.Select(d => new { d.ArchiveTime, d.TempC, d.CO2Percent})
.ToList();
var tempCTupels = actualData.Select(d => new TimeTupel<float>(d.ArchiveTime, d.TempC)).ToList();
var co2Tupels = actualData.Select(d => new TimeTupel<float>(d.ArchiveTime, d.CO2Percent)).ToList();
在实际从IQueryable加载对象之前,您只能选择所需的属性。 在Where语句后使用Select仅加载所需的内容。
一个例子:
假设您有一个看起来像这样的课:
public class Person {
public string Name { get; set; }
public int Age { get; set; }
}
我可以初始化要测试的项目列表:
var people = new List<Person> { new Person { Name = "John", Age = 10 }, new Person { Name = "Archie", Age = 40 } };
然后我们应用一个过滤器:
var filterred = people.Where(p => p.Age > 15).Select(p => p.Name).ToList();
如果我想使用选择创建一个新对象,然后选择一个以上的属性,则可以执行以下操作:
var objFilterred = people.Where(p => p.Age > 15).Select(p => new { FullName = p.Name }).ToList();
您不必使用匿名对象,也可以创建一个仅包含所需属性的新类,然后直接填充该类。
您无法“删除” ToList,因为这实际上是在执行查询。 IQueryable不是数据,它是尚未运行的查询,您可以根据需要链接任意数量的内容。 最后一步是执行它,运行类似于ToList的操作,以实际加载对象。 只要构建了IQueryable,并在完成后执行它,那么执行速度就应该有所提高
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.