views:

65

answers:

2

I want to be able to pass a variable type to a method, mainly so that I can pass an entity framework query to a method that will apply common includes of nested object.

This is what I want to do...

public Person GetPersonByID(int personID)
{
     var query = from Perspn p in Context.Persons
                 where p.PersonID = personID
                 select p;

     ObjectQuery<Person> personQuery = ApplyCommonIncludes<Person>(query);

     return personQuery.FirstOrDefault();
}


public ObjectQuery<T> ApplyCommonIncludes<T>(SomeType query)
{
     return ((ObjectQuery<T>)query)
          .Include("Orders")
          .Include("LoginHistory");
}
+3  A: 

Seems to be you actually want SomeType to be ObjectQuery<T>, right?

public ObjectQuery<T> ApplyCommonIncludes<T>(ObjectQuery<T> query)
{
     return query
          .Include("Orders")
          .Include("LoginHistory");
}

This is valid syntax. Is there any problem with this?

This ought to work and do delayed execution (I think this is what you mean by "without enumerating") until FirstOrDefault() is called.

Anderson Imes
A: 

I ended up creating a different approach. My repository now has a list of string used for Includes. To retain type safety for creating includes, I created the following class:

/// <summary>
/// Builds Includes
/// </summary>
public class IncludeBuilder
{
    /// <summary>
    /// List of parts for the Include
    /// </summary>
    private List<string> Parts;

    /// <summary>
    /// Creates a new IncludeBuilder
    /// </summary>
    private IncludeBuilder()
    {
        this.Parts = new List<string>();
    }


    /// <summary>
    /// Creates a new IncludeBuilder
    /// </summary>
    public static IncludeBuilder Create()
    {
        return new IncludeBuilder();
    }


    /// <summary>
    /// Adds a property name to the builder
    /// </summary>
    public IncludeBuilder AddPart<TEntity, TProp>(Expression<Func<TEntity, TProp>> expression)
    {
        string propName = ExpressionHelper.GetPropertyNameFromExpression(expression);
        this.Parts.Add(propName);

        return this;
    }


    /// <summary>
    /// Gets a value of the include parts separated by
    /// a decimal
    /// </summary>
    public override string ToString()
    {
        return string.Join(".", this.Parts.ToArray());

    }

This allows me to do this...

myPersonRepository.AppendInclude(
     IncludeBuilder.Create()
          .AddPart((Person p) => p.Orders)
          .AddPart((Order o) => o.Items));

The above statement passes expressions to the IncludeBuilder class which then translates the above into "Orders.Items".

I then created helper methods in my RepositoryBase that given an ObjectQuery, will apply the includes, execute the query, and return the result. Not quite what I was looking for, but works well.

Matthew