How to invoke Expression<Func<Entity, bool>> against a collection
Asked Answered
C

2

12

I have an interface that defines a repository from the Repository pattern:

interface IRepository
{
    List<Customer> GetAllCustomers(Expression<Func<Customer, bool>> expression);
}

I've implemented it against Entity Framework:

class EntityFrameworkRepository
{
    public List<Customer> GetAllCustomers(Expression<Func<Customer, bool>> expression)
    {
        return DBContext.Customers.Where(expression).ToList();
    }
}

That seems to work well, it allows me to do something like:

var customers = entityFrameworkRepository.Where(
    customer => String.IsNullOrEmpty(customer.PhoneNumber)
);

Now I'd like to have an InMemoryRepository for testing and demo purposes. I attempted to create one:

class InMemoryRepository
{
    Dictionary<int, Customer> Customers {get; set;} = new Dictionary<int, Customer>();

    public List<Customer> GetAllCustomers(Expression<Func<Customer, bool>> expression)
    {
        //what do I put here?
    }
}

As you can see in the above code, I'm stumped on what to do for InMemoryRepository.GetAllCustomers implementation. What should I do there to filter the Customers by the provided expression and return the results?

I tried:

return Customers.Where(expression));

But obviously it's expecting a Func<KeyValuePair<int, Customer>, bool> so I get a compilation error:

Error CS1929 'Dictionary' does not contain a definition for 'Where' and the best extension method overload 'Queryable.Where(IQueryable, Expression>)' requires a receiver of type 'IQueryable' DataAccess.InMemory

Carmacarmack answered 24/9, 2015 at 3:51 Comment(0)
P
17

Try .AsQueryable() method:

return Customers.Values.AsQueryable().Where(expression);
Proliferation answered 24/9, 2015 at 3:53 Comment(4)
I spent like an hour on this, and you get me in less than a minute. Fantastic. A quick correction, it's Customers.Values.AsQueryable().Where(expression);Carmacarmack
@Carmacarmack yes, of couse. glad to help!Proliferation
Why is this necessary? EntitySet already implements IQueryable, right?Lentamente
@Protectorone because Customers.Values is not EntitySetProliferation
R
-1

Example

Expression<Func<Products, bool>> expresionFinal = p => p.Active;

if (mydate.HasValue)
{
    Expression<Func<Products, bool>> expresionDate = p => (EntityFunctions.TruncateTime(c.CreatedDate) <= mydate);
    expresionFinal = PredicateBuilder.And(expresionFinal, expresionDate );
}

IQueryable<T> query = dbSet;


    query = query.Where(expresionFinal);
Redden answered 24/9, 2015 at 11:23 Comment(2)
Not sure what you're going for here? The expression is already set, I can't change the form.Carmacarmack
You need a Generic repository like this : public class GenericRepository<T> : IGenericRepository<T> , IDisposable where T : class {internal DbContext context; internal DbSet<T> dbSet; public GenericRepository(DbContext context) { this.context = context; this.dbSet = context.Set<T>(); } public virtual IEnumerable<T> Get(Expression<Func<T, bool>> filter = null) { IQueryable<T> query = dbSet; query = query.Where(filter); return query.ToList(); } }Redden

© 2022 - 2024 — McMap. All rights reserved.