'Suggestions for designing complex LINQ code

What are your suggestions for designing linq code in project? Especially, I`m interesting in code design of big and complex linq queries?

For example, you know, that you need to write a lot of huge linq stuff, maybe some of your code will have duplicate parts, maybe not, and you need:

  1. Make the code easily supportive - means, if you need to change something . - you are changing one thing, not many

  2. Make the code easy to read - means, if you need to find something - you easily doing this.

You can use your examples, maybe your practice. Maybe some patterns, that you saw anywhere - anything.

Saying linq I mean any linq, linq to sql, linq to objects, linq to xml, etc.



Solution 1:[1]

you can write extensions for your objects;

Main code;

IQuerable itemList = _coreRepository.GetSomeItems()
                .WithStates(OperationIdentity.SendToSomeWhere)
                .BetweenDates(StartDate, EndDate);

Extension;

public static IQueryable<SomeObject> BetweenDates(this IQueryable<SomeObject> query, DateTime startDate, DateTime endDate)
        {
            return from p in query
                   where p.CompletedDate >= startDate && p.CompletedDate < endDate
                   select p;
        }

Solution 2:[2]

I like to put aside big Select statements that are used many times using extension methods.

public static IQueryable<SomeEntityPM> SelectEntityPM(this IQueryable<SomeEntity> entities)
{
     return entities.Select(a => new SomeEntityPM { ... });
}

Usage:

 ObjectCtx.SomeEntities.SelectEntityPM();

Solution 3:[3]

One useful pattern for this is creating a reusable predicate library. Check out this page on the LINQ PredicateBuilder for more info.

Solution 4:[4]

A vew things I often do:

1) Layout: always start a query at the next line. Example: Don't do this

var allCustomersThatDontContainUnpayedOrders = from customer in db.Customers
                                               where customer.Orders ...
                                               select customer;

But do this:

var allCustomersThatDontContainUnpayedOrders = 
    from customer in db.Customers
    where customer.Orders ...
    select customer;

2) Use multiple where clauses where you can. I try to find the second snippet more readable than the first:

var results =
    from customer in db.Customers
    where customer.Name.Contains(search) && customer.Address.City != null &&
       customer.Employee.IsSenior
    select customer;

var results =
    from customer in db.Customers
    where customer.Name.Contains(search)
    where customer.Address.City != null
    where customer.Employee.IsSenior
    select customer;

3) Prevent joins if you can. LINQ to SQL often allows you to just 'dot' over all parent-child relations without using hard-to-understand join statements.

4) Often you will see that many queries look alike. You might always want to filter certain records based on rights of a user. You can extract this code in a method:

var customers = db.Customers;

customers = FilterBasedOnUserRights(customers, currentUser);

public static IQueryable<Customer> FilterBasedOnUserRights(
    IQueryable<Customers customers, User currentUser)
{
    return
        from customer in customers
        where [big complicated where clause]
        select customer;
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 NetSide
Solution 2 Stephane
Solution 3 Chris Fulstow
Solution 4 Steven