Reusing parts of LINQ queries is easily done by chaining methods returning IQueryable. Unfortunately that doesn’t cover some senarios like reusing member initialization lists. To handle such a situation I wrote a Mergeextension method for select expressions.
For this post we’ll load the data required for a list of cars and a detail view for one car. When loading the details, more fields are required than when just loading the list. With the merging helper method we can reuse the query for the basic list and just extend it with the added properties.
The basic info for the list view is held in a CarBasicInfoDTO class. The data for the detail view is held in a CarExtendedInfo class which is derived from the CarBasicInfo class. A helper method contains the Select() call to map Car entities to the basic DTO. Now the Merge extension method can be used to merge an expression with the initialization of the additional fields for the extended DTO with the existing helper method for the basic fields.
private Expression<Func<Car, CarBasicInfo>> basicSelect =
c =>new CarBasicInfo
{
CarId = c.CarId,
RegistrationNumber = c.RegistrationNumber};var car = ctx.Cars.Select(basicSelect.Merge(c =>new CarExtendedInfo
{
Color = c.Color,
BrandName = c.Brand.Name})).Single(c => c.RegistrationNumber=="ABC123");
private Expression<Func<Car, CarBasicInfo>> basicSelect =
c => new CarBasicInfo
{
CarId = c.CarId,
RegistrationNumber = c.RegistrationNumber
};
var car = ctx.Cars.Select(basicSelect.Merge(c => new CarExtendedInfo
{
Color = c.Color,
BrandName = c.Brand.Name
})).Single(c => c.RegistrationNumber == "ABC123");
The RegistrationNumber field is not mentioned in the init list – it is populated by the basic select in the SelectBasicInfo helper method. To accomplish this some (non trivial) rewriting of expression trees is in the Merge method.
Subscribing to an event with a method that requires state is a pain because it often requires a class to be created to hold that state. Fortunately we can use a lambda expression to have the compiler create that state for us instead.
It is not an uncommon scenario to have an event handler that will do something with some specific data when an event fires. An example I had lately was a mail helper that only would send the email after the Entity Framework DbContext successfully has executed SaveChanges(). That way I knew that the database was properly updated with the state that the mail was indeed sent. Everything was wrapped in a transaction too, so if the mail failed to send the entire transaction was rolled back, undoing the database changes.
Anyway, that code could be a pain to write. I would have to create a separate object that held a reference to the e-mail to send and subscribe a method of that class to the DbContext’s SavingChanges() event (ok, it’s a bit more complicated than that to get to the SavingChanges event, but that’s another topic). Instead I used a lambda expression that creates a closure that automatically captures the required variable.