문제

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

도움이 되었습니까?

해결책

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.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top