Reputation: 1738
I have an application using the Repository pattern to abstract how data is retrieved. I plan on using a web service for retrieving the data, but during development will just mock it out. However, I am stuck on how to get a find method working. I have the following so far, but I am not sure that query.Compile()
is the right thing to be doing (no examples I have found do that). I get a compiler error saying there is no overload for Linq's Where method that takes a System.Linq.Expressions.Expression
. Here is where I am at so far:
public async Task<IEnumerable<Customer>> FindAsync(Expression<Func<Customer, bool>> query)
{
var allCustomers = await GetAllAsync(true);
return allCustomers.Where(query.Compile());
}
At some point, I would like to figure out how to avoid retrieving all customers and then applying the expression also, but am not sure how I can pass the expression to a REST webservice so the filtering can happen at the data access layer.
Upvotes: 3
Views: 3353
Reputation: 5103
The implementations of Repository pattern I've seen generally look like this (using Entity Framework):
public class Repository<T> where T : class
{
private readonly DbSet<T> _queryableBase;
public Repository(DbSet<T> queryableBase)
{
_queryableBase = queryableBase;
}
public T Select(IFilter<T> filterClass)
{
return filterClass.Filter(_queryableBase.AsQueryable()).First();
}
public IEnumerable<T> SelectMany(IFilter<T> filterClass)
{
return filterClass.Filter(_queryableBase.AsQueryable());
}
public void Delete(T item)
{
_queryableBase.Remove(item);
}
public void Add(T item)
{
_queryableBase.Add(item);
}
}
Then the filter object:
public interface IFilter<T>
{
IEnumerable<T> Filter(IEnumerable<T> queryableBase);
}
Example filtering implementation:
class FilterChris : IFilter<ATestObject>
{
public IEnumerable<ATestObject> Filter(IEnumerable<ATestObject> queryableBase)
{
return queryableBase.Where(o => o.FirstName == "Chris");
}
}
public class ATestObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
Note that filters can chain.
Upvotes: 2
Reputation: 26406
At some point, I would like to figure out how to avoid retrieving all customers and then applying the expression also, but am not sure how I can pass the expression to a REST webservice so the filtering can happen at the data access layer.
Assuming your client app is written in C# you could use breeze-sharp:
http://www.breezejs.com/breeze-sharp-documentation/query-examples#whereSimple
BreezeSharp communicates with any service that speaks HTTP and JSON. Are you serving data with Web API, OData or MVC backed by Entity Framework in front of SQL Server? Breeze has a great out-of-the-box story.
BreezeSharp would allow you to write code like this on the client:
var query3 = query1.Where(td => !td.IsArchived && !td.IsDone);
var activeTodos = awaitManager.ExecuteQuery(query3);
Upvotes: 1