1

I am trying to write a dynamic query using Expression Tree. We have following entities in our schema:

  • Tenant
  • Employee
  • Services

There is a 1 to many relationship between Tenant and Serivces and Many to Many relationship between Employee and Serivces. Both Tenant and Employee contains the ICollection of Services.

Now I have to write the following query dynamically:

  context.{EntityDbSetResolveAtRunTime out of Tenant OR Employee entity}
         .SingleOrDefault(p => 
          p.{PropertyResolveAtRunTime out of TenantId or EmployeeId} == id)
         .Services;

Below is the code i tried yet is:

public class ServiceRpository<TEntity> : where TEntity : class
{
    private DbSet<TEntity> dbset;

    public ServiceRepository(MyContext context)
    {
      dbset = context.Set<TEntity>();
    }

    public List<Services> Get(string id)  
    {
       //p 
       ParameterExpression predicateVariable = Expression.Parameter(typeof(TEntity), "p");
       //p => p.TenantId OR p => p.EmployeeId
       Expression left = Expression
               .Property(predicateVariable, typeof(TEntity)
               .GetProperty(typeof(TEntity).Name + "Id"));
       //id
       Expression rightConstant = Expression.Constant(id);
       //p => p.TenantId == id OR p => p.EmployeeId == id
       Expression predicateBody = Expression.Equal(left, rightConstant);

       // predicateBody variable contains 
       // p => p.TenantId == id OR p => p.EmployeeId == id

       //The below code will give us the Tenant Or Employee entity
       var entity = dbset.SingleOrDefault(Expression.Lambda<Func<TEntity, bool>>(
           predicateBody, new ParameterExpression[] { predicateVariable }));


       // Now the problem is how i get Serivces out of the entity, something like
       // entity.Services;
       // and what should be 
       // the return type of this function which orignally i want List<Services>

    }
} 

Please check the comments in the code.

Thanks!

1 Answer 1

1

I have no way to test it right now, but following should work (or at least guide you into right direction).

Add Include call to fetch services:

//The below code will give us the Tenant Or Employee entity
var entity = DbSet.Include("Services").SingleOrDefault(
    Expression.Lambda<Func<TEntity, bool>>(predicateBody, new ParameterExpression[] { predicateVariable }));

Get your Services property value as IEnumerable<Service> and call ToList() to make sure List<Service> is returned:

return ((IEnumerable<Service>)typeof(TEntity).GetProperty("Services").GetValue(entity, null)).ToList();
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.