Search code examples
entity-frameworklinq-to-entitiesiqueryable

IQueryable dynamic set property


Who to set property from join expression

public interface IHiddenEntity
{
  bool Hidden { get; set;}
}
public interface IEntity 
{
   long Id { get; set;}
   string Name { get; set;}
}

public class Entity: IEntity, IHiddenEntity 
{
   public long Id { get; set;}
   public string Name { get; set;}
   public bool Hidden { get; set;}
}

public class Hidden 
{
   public string TableName {g et; set; }
   public long RecordId { get; set; }
}

public class Person: Entity{ ... }


public IQueryable<T> All(bool loadHidden = false)
  where T : class, IEntity, IHiddenEntity 
{
    string tableName = "<T> name";
    return from x in Context.Set<T>()
           join h in Context.Set<Hidden>().Where(record => record.TableName == tableName) on x.Id equals h.RecordId into hr
            from h_r in hr.DefaultIfEmpty()
            where loadHidden ? true : h_r == null
            select x;
}

But I can’t understand how to set the value in the Hidden field.

  1. Only IQueryable needs to be returned, because there are still conditions for the method to execute.
  2. It is also impossible to convert to IEnumerable: this is not the final value (see above).

UDP: Options to create a selection for each model are not considered - a lot of models with a huge number of fields!


Solution

  • So, found an idea. Create wrapped object with needed properties and cast to entity type after query executed.

    internal EntityWrapper<T>
    {
          public T Model { get; set; }
          public bool Hidden { get; set; }
    }
    
    public IQueryable<T> All(bool loadHidden = false)
      where T : class, IEntity, IHiddenEntity 
    {
        string tableName = "<T> name";
        var query = from x in Context.Set<T>()
               join h in Context.Set<Hidden>().Where(record => record.TableName == tableName) on x.Id equals h.RecordId into hr
                from h_r in hr.DefaultIfEmpty()
                select new EntityWrapper<T>(){ Model = x, Hidden = h_r != null};
    
        if(!loadHidden)
            query = query.Where(x => !x.Hidden);
    }
    

    And cast after build sql query and results with wrapped object.

        Expression<System.Func<EntityWrapper<T>,T> castFunc = x => x.Select(wr => {wr.Model.Hidden = wr.Hidden; return wr.Model;});
    

    Cast only IEnumerable<EntityWrapper<T>> object.

    
    var result = castFunc(<query>.ToList());