Pages

Saturday, August 28, 2010

Dictionaries and LINQ

Because all IDictionary implementations are also enumerable, we can
run LINQ queries against them. Given the RecordCache class in Example 9-5, we might
choose to implement the cache item removal policy as shown in Example 9-10.
Example 9-10. LINQ query with dictionary source
private void DiscardAnyOldCacheEntries()
{
// Calling ToList() on source in order to query a copy
// of the enumeration, to avoid exceptions due to calling
// Remove in the foreach loop that follows.
var staleKeys = from entry in cachedRecords.ToList()
where IsStale(entry.Value)
select entry.Key;
foreach (int staleKey in staleKeys)
{
cachedRecords.Remove(staleKey);
}
}

But it’s also possible to create new dictionaries with LINQ queries. Example 9-11 il-
lustrates how to use the standard ToDictionary LINQ operator.
Example 9-11. LINQ’s ToDictionary operator
IDictionary buildingIdToNameMap =
MyDataSource.Buildings.ToDictionary(
building => building.ID,
building => building.Name);

This example presumes that MyDataSource is some data source class that provides a
queryable collection containing a list of buildings. Since this information would typi-
cally be stored in a database, you would probably use a database LINQ provider such
as LINQ to Entities or LINQ to SQL. The nature of the source doesn’t greatly matter,
though—the mechanism for extracting the resources into a dictionary object are the
same in any case. The ToDictionary operator needs to be told how to extract the key
from each item in the sequence. Here we’ve provided a lambda expression that retrieves
the ID property—again, this property would probably be generated by a database map-
ping tool such as the ones provided by the Entity Framework or LINQ to SQL. (We
will be looking at data access technologies in a later chapter.) This example supplies a
second lambda, which chooses the value—here we pick the Name property. This second
lambda is optional—if you don’t provide it, ToDictionary will just use the entire source
item from the stream as the value—so in this example, leaving out the second lambda
would cause ToDictionary to return an IDictionary (where Building is
whatever type of object MyDataSource.Buildings provides).
The code in Example 9-11 produces the same result as this:
var buildingIdToNameMap = new Dictionary();
foreach (var building in MyDataSource.Buildings)
{
buildingIdToNameMap.Add(building.ID, building.Name);
}

No comments:

Post a Comment