3

I have method that expects the following parameters:

public IQueryable<TEntity> GetAllIncluding(params Expression<Func<TEntity, object>>[] includeProperties)
{
    foreach (var includeProperty in includeProperties)
    {
        dbSet.Include(includeProperty);
    }
    return dbSet;
}

Here's how I pass in my params:

IQueryable<User> users = repo.GetAllIncluding(u => u.EmailNotices, u => u.EmailTemplatePlaceholders, u => u.Actions);

However, I need to be able to check certain conditions before I pass them in or not.

For example, if I have a variable useEmailNotices = false, then I don't want to pass in EmailNotices but if it's true then I do. I need to do this for all three. I know there's a long way to do this but I was hoping that there was a one line short way or a param builder function or something of that nature.

Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93
RichC
  • 7,829
  • 21
  • 85
  • 149
  • Repository... exposing IQueryable... Sigh... – Phill Feb 14 '14 at 16:40
  • @Phill What do you recommend? I actually got that snippet of code from [Julie Lerman](http://pluralsight.com/training/Authors/Details/julie-lerman) – RichC Feb 14 '14 at 17:03
  • Exposing IQueryable is a leaky abstraction, if you're going to expose that you may as well do away with the repository to begin with and just use your UoW directly. – Phill Feb 14 '14 at 17:04
  • Secondly you're got a TEntity which means you're using a base repository... http://www.philliphaydon.com/2014/01/if-youre-going-to-use-repositories-dont-have-generic-or-base-repositories/ – Phill Feb 14 '14 at 17:05

2 Answers2

4

What about changing the signature of the method to

public IQueryable<TEntity> GetAllIncluding(IEnumerable<Expression<Func<TEntity, object>>> includeProperties)

defining your conditional logic elsewhere

var args = new List<Expression<Func<TEntity, object>>>();
if (useEmailNotices)
    args.Add(u => u.EmailNotices);

and then simply calling the method like

IQueryable<User> users = repo.GetAllIncluding(args);
Ondrej Janacek
  • 12,486
  • 14
  • 59
  • 93
  • @DavidKhaykin There's not exactly too much options here, is there? :) – Ondrej Janacek Feb 14 '14 at 16:41
  • Yep, only the List has to have the User entity, not the generic TEntity, I think. – Dmitriy Khaykin Feb 14 '14 at 16:43
  • Sounds like this is my only option. i was hoping to not have to always have this line `var args = new List>>();` every time I use it but I just did an override so I can still use the easy way if there are no conditional params. – RichC Feb 14 '14 at 16:45
  • @RichC: you can obfuscate that into a method if you like but with needed conditions you'll have to declare a list and use more than one line to populate it. – Dmitriy Khaykin Feb 14 '14 at 16:47
  • @DavidKhaykin Not really. If it's inside a generic class or method then it's valid to user `TEntity`. – Ondrej Janacek Feb 14 '14 at 17:32
  • oddly enough, this now prevents eager loading from occurring. I set the conditions equal to true and I step through the options getting included to the dbset but they don't all return in the same query. Each child entity makes a separate call. When I run the same code the normal way (original code posted) it works as expected. – RichC Feb 14 '14 at 18:39
  • Interesting... I went back to using my original GetAllIncluding() method and just to an `IQueryable users = repo.GetAllIncluding(args.ToArray());` and that fixed it. Can you edit your answer to reflect this for future reference? – RichC Feb 14 '14 at 18:52
  • @RichC Interesting. I'm glad you figured it out on your own, I wouldn't be able to help you with this probably. – Ondrej Janacek Feb 14 '14 at 18:53
2

Instead of Params, use a List<T>, declared with the actual entity you wish to pass in:

var funcList = new List<Expression<Func<User, object>>>();

funcList.add(u => u.EmailTemplatePlaceholders);

if (useEmailNotices)
    funcList.add(u => u.EmailNotices);

And the method signature would now be:

public IQueryable<TEntity> GetAllIncluding(List<Expression<Func<TEntity, object>> includeProperties)
{
    foreach( ... )
}
Dmitriy Khaykin
  • 5,238
  • 1
  • 20
  • 32