I came across a colleagues code and thought it was possibly inefficient
bool any = (from c in listDeviceMaxDate
where c.DeviceKey == m_deviceList[i].deviceKey
select c).Any();
if (!any)
{
latestDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
}
else
{
// from the list we have get the lastest max date from the flow table
DeviceDateTimeItem temp = (from c in listDeviceMaxDate
where c.DeviceKey == m_deviceList[i].deviceKey
select c).First();
latestDate = Convert.ToDateTime(temp.dateTimeMax);
}
My first instinct is to store the linq query and then just reference it as needed but then I realised that the First() operator may prevent linq from actually getting ALL the rows which an unconstrained query would do.
How I initially thought about restructuring the code:
var deviceList = from c in listDeviceMaxDate
where c.DeviceKey == m_deviceList[i].deviceKey
select c;
if (!deviceList.Any())
{
latestDate = (DateTime)System.Data.SqlTypes.SqlDateTime.MinValue;
}
else
{
// from the list we have get the lastest max date from the flow table
DeviceDateTimeItem temp = deviceList.First();
latestDate = Convert.ToDateTime(temp.dateTimeMax);
}
My question is does the First() call on the second linq query prevent it from returning all results, and as such, is it actually quicker to do it the original way?
It actually depends on what LINQ implementation it is. If it is LINQ-to-Objects (i.e.
IEnumerable<T>), then it is basically just enumerating the data whatever it is, and returning the first item if one. SoFirst()is the moral equivalent of:and
Any()should compare well to:(it probably uses a raw iterator in the actual implementation, rather than
foreach)However! If it is LINQ-to-anything-else, all bets are off. LINQ queries (especially
IQueryable<T>) are designed to be composable – and I would expect LINQ-to-SQL, for example, to makeFirst()into aselect TOP 1 ...TSQL query, and similarly for most other database-backends. So yes, telling it that you only want one row should be helpful. However! I would also expect.Any()to do something very similar, so that shouldn’t (in theory) be a big difference. In a perfect world, it might even useexists(...)in the TSQL, but the world is far from perfect.The way to find out: attach a sql tracer, and see what the final TSQL was.
The ultimate way to do this is simpler: