views:

193

answers:

1

Hi,

I want to use a generic repository to standardise some of my data access. What I want is to be able to have a function defined in the interface representing the basic fields of my entity, so that I can use it to filter the results. This should be compilable into Linq-To-Sql.

e.g.

interface IEntity {
  Expression<func<bool>> FilterQuery(string filter)
}

partial class AnEntity : IEntity
{
  public string AName {get; set;}

  Expression<func<bool>> FilterQuery(string filter)
  {
    return AName.Contains(filter);
  }
}

class List<T> : where T : class, IEntity
{
  private IQueryable<T> items;
  public IQueryable<T>  show(string filter)
  {
    items = items.Where(AN => AN.FilterQuery(filter));
    return items;
  }
}

However, I typically get errors like:

Cannot convert lambda expression to delegate type 'System.Func<T,int,bool>' because some of the return types in the block are not implicitly convertible to the delegate return type

What is the best way of achieving my goal, of having something generic defined on an entity which can be using in a linq to sql where clause?

+1  A: 

The lambda for Where needs to take the entity type; I would expect that you would need:

interface IEntity<T> where T : class {
   Expression<Func<T, bool>> FilterQuery(string filter);
}

partial class AnEntity : IEntity<AnEntity>
{
  public string AName {get; set;}

  Expression<Func<AnEntity,bool>> IEntity<AnEntity>.FilterQuery(string filter)
  {
    return x => x.AName.Contains(filter);
  }
}

However; the FilterQuery method doesn't feel like an entity responsibility... (separation of concerns); which is why it isn't helpful in the "list" case; maybe you need to move that to the list? But when it works, something like:

T template = new T(); // this is a horrible way to get the filter!!!
                      // and illustrates that this method doesn't belong on
                      // this type; only done this way to fit the question's
                      // pretext - which I believe is... suboptimal.
var filterQuery = template.FilterQuery(filter);
items = items.Where(filterQuery);
Marc Gravell
Thanks Marc...That's a good solution, but I see what you mean about 'suboptimal'... I'll add a comment to rephrase the question, see if there is a better way to achieve what I want.
stew
I'm really just talking about roles; the method to filter *instances* of type A doesn't really sit well as an instance method of type A. It would work on the repository for the type, or as a *static* method on the type (but static methods can't participate in interfaces, of course).
Marc Gravell
Yes, I would have preferred a static method... but couldn't use one for the exact reason you describe.
stew