I'm trying to filter a LINQ-to-entities query in a generic way, but I keep getting an error. Here is a piece of code:
private IQueryable<T> FilterDeletedEntities<T>(IQueryable<T> entities)
{
if (typeof(IDeletable).IsAssignableFrom(typeof(T)))
{
var deletableEntities = (IQueryable<IDeletable>)entities;
deletableEntities = deletableEntities.Where(entity => !entity.Deleted);
entities = (IQueryable<T>)deletableEntities;
}
return entities;
}
Basically I'm trying to filter out deleted entities (i.e. 'Deleted' field is 'true'), if and only if the entity is IDeletable (i.e. it has the 'Deleted' field). The problem is that I can't cast IQueryable< IDeletable > back to IQueryable< T >.
Any ideas on how to fix this? And before you ask: yes, this method has to be generic.
Thanks in advance!
But you can use Cast<T>()
to convert it.
entities = deletableEntities.Cast<T>();
You could also use it to case to IDeletable as well, for example,
private IEnumerable<T> FilterDeletedEntities<T>(IQueryable<T> entities)
{
if (typeof(IDeletable).IsAssignableFrom(typeof(T)))
{
return entities.ToList()
.Cast<IDeletable>()
.Where( e => !e.Deleted )
.Cast<T>();
}
return entities.ToList();
}
I was able to solve my problem by doing this:
private IQueryable<T> FilterDeletedEntities<T>(IQueryable<T> entities)
{
if (typeof(IDeletable).IsAssignableFrom(typeof(T)))
{
var deletableEntities = (IQueryable<IDeletable>)entities;
return deletableEntities.Where(entity => !entity.Deleted).Cast<T>();
}
return entities;
}
Thanks to tvanfosson for the inspiration.
If you can assume that no one will need to call this method with T that does not implement IDeletable, you can restrict T:
private IQueryable<T> FilterDeletedEntities<T>(IQueryable<T> entities) where T : IDeletable
As a bonus, you won't need to cast anything or use reflection to test for IDeletable.