0

I have a list on SharePoint, where I am trying to load fields for this list like following:

        var lists = context.Web.Lists;
        context.Load(lists, n => n.Include(x => x.Title,
                                           x => x.Fields.Include(
                                               z => z.Title, 
                                               z => z.InternalName, 
                                               z => z.TypeDisplayName)));
        context.ExecuteQuery();

The following part of the code I use quite often in my code, while working with other lists:

                          x => x.Fields.Include(
                                               z => z.Title, 
                                               z => z.InternalName, 
                                               z => z.TypeDisplayName)

I would like to know if there is a way how to simplify inserting this .Include statement in my code (so that in case I will have to add more properties in the future, I dont have to rewrite all my code everywhere but only in one place).

I have tried to create custom LINQ Extension, but it failed as it is probably expecting sort of a Expression<Func<T,Y>> (I guess).

Any help regarding this matter would be more than appreciated!

Robert J.
  • 2,176
  • 4
  • 26
  • 49

1 Answers1

1

Since the Load method expects an Expression<Func<T, object>>, and lists is presumably IQueryable<Something> you can use something like:

public static Expression<Func<IQueryable<Something>, Object>> IncludeCommonFields()
{
    // since the method returns an Expression, this will actually
    // get compiled to an expression tree
    return input => input.Fields.Include(z => z.Title, 
                                         z => z.InternalName, 
                                         z => z.TypeDisplayName);
}

Evaluating the function should create a new instance of the expression tree:

var lists = context.Web.Lists;
context.Load(lists, n => n.Include(x => x.Title,
                                   IncludeCommonFields());
context.ExecuteQuery();

If it's invoked often, you might also choose to instantiate it only once:

static readonly Expression<Func<IQueryable<Something>, Object>> _commonIncludes 
   = input => input.Fields.Include(z => z.Title, 
                                        z => z.InternalName, 
                                        z => z.TypeDisplayName);

context.Load(lists, n => n.Include(x => x.Title,
                                   _commonIncludes);
Groo
  • 45,930
  • 15
  • 109
  • 179
  • Disclaimer: I never used EF 4.1 so I am not sure about `Include` signature, I am presuming it's [an extension method on `IQueryable`](https://msdn.microsoft.com/en-us/library/gg671236(v=vs.103).aspx). – Groo Sep 23 '16 at 09:13
  • I have already tried to do this, but this fails as it tries to evaluate expression right away, rather than evaluating it at once when I call `context.ExecuteQuery()` – Robert J. Sep 23 '16 at 10:10
  • @RobertJ.: that's weird, can you post how you used the method? Return type is still `IQueryable` so nothing should be evaluated at this time. – Groo Sep 23 '16 at 12:42
  • @RobertJ.: Ok, I got it, these methods accepts [expressions](https://msdn.microsoft.com/en-us/library/office/ee544003(v=office.14).aspx), so the expression tree should be evaluated at compile time. – Groo Sep 23 '16 at 13:45
  • 1
    @RobertJ.: great! I've also updated the answer since you probably don't need to create a new instance of the expression tree each time. The first approach gives you the option of controlling the instantiation (e.g. by passing a parameter to `IncludeCommonFields`), but the second one should be better if it's just an immutable expression shared between all queries. – Groo Sep 24 '16 at 08:22