Question

How can I filter the IsSoftDeleted items out of this DbSet?

var type = GetTypeFromString("Whatever");
var whatevers = Set(type);

Method

public dynamic Set(Type type)
{
    var set = dbContext.Set(type);
    return set;
}

Model

public class Whatever : BaseEntity
{
    public virtual string Name { get; set; }
}
public class BaseEntity
{
   public virtual int Id { get; set; }
   public virtual bool? IsSoftDeleted { get; set; }
}

EDIT: forgot to show Whatever derives from BaseEntity

Was it helpful?

Solution

Your Whatever class doesn't have any IsSoftDeleted property, so there's nothing to filter. I'm going to assume Whatever is derived from BaseEntity.

The main problem is that IQueryable<T>.Where doesn't actually exist: it's an extension method, and extension methods don't play nice with dynamic types. If the compiler can see a type implements IQueryable<T>, you can type var.Where(...) and have the compiler resolve it to System.Linq.Queryable.Where(var, ...). Since the type is dynamic in your example, the compiler doesn't know it implements IQueryable, and will report an error when you try to call Where.

You can cast the DbSet to IQueryable<BaseEntity> (as long as Type has BaseEntity as a base class), and call any filter on that. Do you actually use the dynamic type feature? If not, you can also consider dropping your custom Set function, and using the default DbContext.Set function.

var query = (from e in (IQueryable<BaseEntity>)dbContext.Set(type)
             where e.IsSoftDeleted != true
             select e);

Note: this is not the same as using dbContext.Set(type).Cast<BaseEntity>(): that won't work, because a DbSet<BaseEntity> and a DbSet<Whatever> are incompatible. It is only with IQueryable and other interfaces with "out" type arguments that you can do this.

OTHER TIPS

The problem is that Set(Type type) returns a non-generic DbSet. To apply your filter you must cast it to a generic IQueryable<T>:

var set = ((IQueryable<BaseEntity>)dbContext.Set(type))
              .Where(be => be.IsSoftDeleted.HasValue && !be.IsSoftDeleted.Value);

This works only if type is derived from BaseEntity or BaseEntity itself, otherwise you'll get a runtime exception.

The resulting set is of type IQueryable<BaseEntity>, so the question is, how useful this result is and how you can apply further filters for your derived entities like Where(w => w.Name == "abc"). At least, I could not get compilable code by making set of type dynamic. I also would not like to lose all strong typing.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top