Problem: You have a collection of objects. Each object has a number of children. You want all the children matching a criteria, AND the parent. The child does not reference the parent.
Solution: You can use Linq to
- From the context of all the parents, select all the children with the “SelectMany” method.
- Construct and select instances of an anonymous type combining the parent and child. (You can do this because the context is that of the parent.)
- Apply your filtering criteria.
Example: Select the five most recently modified children (and parent)
class Program
{
static void Main()
{
var allParents = new StupidFactory().ConstructParents(100);
var fiveMostRecentChildrenAndParent = allParents
.SelectMany(parent => parent.Children)
.Select(child => new { Child = child, Parent = allParents.Where(parent => parent.Children.Contains(child)).Single() })
.OrderByDescending(anonymousCombo => anonymousCombo.Child.LastModified)
.Take(5);
foreach (var childAndParent in fiveMostRecentChildrenAndParent)
{
Console.WriteLine("{0} modified on {1} (belongs to {2})", childAndParent.Child.Name, childAndParent.Child.LastModified.ToShortDateString(), childAndParent.Parent.Name);
}
}
}
public abstract class Entity
{
public string Name;
}
public class Parent : Entity
{
public List<Child> Children = new List<Child>();
}
public class Child : Entity
{
public DateTime LastModified;
}
public class StupidFactory
{
private readonly Random _random = new Random();
private int _childCount;
private int _parentCount;
private Child ConstructChild()
{
return new Child { Name = "Child_" + _childCount++, LastModified = DateTime.Now.AddDays(-_random.Next(0, 365)) };
}
private Parent ConstructParent()
{
var result = new Parent { Name = "Parent_" + _parentCount++ };
var childCount = _random.Next(0, 11);
for (var i = 0; i < childCount; i++)
{
result.Children.Add(ConstructChild());
}
return result;
}
public IList<Parent> ConstructParents(int count)
{
var result = new List<Parent>();
for (var i = 0; i < count; i++)
{
result.Add(ConstructParent());
}
return result;
}
}
John McDowall
