dlux
dlux

Reputation: 121

With a generic repository for entity framework, how do I query entities which implement a specific interface?

I am using the Repository pattern with Entity Framework and have implemented a generic repository.

For certain types of entities though, I do not want to remove the record from the database, instead if want to set the IsDeleted bool to true.

To this effect, I have create this simple interface:

IEntityProtectedDelete.cs

public interface IEntityProtectedDelete
{
    bool IsDeleted { get; set; }
}

Is is implemented on my entity like this:

Queue.cs

public class Queue : IEntityProtectedDelete
{
    public Queue() 
    {
        IsDeleted = false;
    }

    [Key]
    public int QueueId { get; set; }

    [Required]
    public string Name { get; set; }

    [Required]
    public bool IsDeleted { get; set; }
}

Below is a portion of the generic repository I am using. The Delete method works as expected, and set the IsDelete property to true when the above Interface is used.

However, I can't quite figure out how to correctly query the database if the entity implements IEntityProtectedDelete.

GenericRepository.cs

public class GenericRepository<T> where T : class
{
    protected DBContext context;
protected IDBSet dbSet;

    public GenericRepository(IContext context)
    {
        this.context = context;
    this.dbSet = context.Set<T>();
    }

    public virtual void Delete(T entity)
    {
        dbSet.Attach(entity);
        if (entity is IEntityProtectedDelete)
        {
            (entity as IEntityProtectedDelete).IsDeleted = true;
            context.Entry(entity).State = EntityState.Modified;
        }
        else { dbSet.Remove(entity); }  
    }

    public virtual IEnumerable<T> GetAll()
    {
        if (typeof(IEntityProtectedDelete).IsAssignableFrom(typeof(T)))
        {
            return context.Set<T>().OfType<IEntityProtectedDelete>().Where(e => e.IsDeleted == false).ToList() as IEnumerable<T>;
        }
        else { return context.Set<T>().ToList(); }
    }
}

In the GetAll() method, the OfType<> throws the exception:

'IEntityProtectedDelete' is not a valid metadata type for type filtering operations. Type filtering is only valid on entity types and complex types."

If this isn't going to work, what other options do I have?

Upvotes: 2

Views: 1532

Answers (1)

Wiktor Zychla
Wiktor Zychla

Reputation: 48279

Soft Delete pattern for Entity Framework has been discussed on SO and the accepted solution is described here

http://www.wiktorzychla.com/2013/10/soft-delete-pattern-for-entity.html

The trick is to define your IsDeleted as a discriminator column so that EF automatically appends filtering subqueries.

Upvotes: 2

Related Questions