0

I have many entities which were generated by EF against the existing database. Most of these entities have a "name" property. I would like a method which takes in an expression against a generic type, and passes in a string value which will ultimately be compared against the name property of the underlying entity.

So far, I have something like this:

T SpecialLookup(DbSet<T> dbSet, Func<T, string, bool> exp, string specialParam) 
where T: class, new() {
  //here we can do something with specialParam first like clean it up.
  //now pass in the specialParam to the underlying query which can 
  //ultimately look up a matching object by "name == specialParam".
  var predicate = PredicateBuilder.New<T>(x => exp(x, specialParam));
  var obj = dbSet.AsExpandable().SingleOrDefault(predicate);
  return obj;
}

the idea here is then I can call the lookup function and pass in a special value, and a delegate which will be called upon the DbSet using the special value as a param.

SpecialLookup(dbContext.SomeEntities, 
 delegate(SomeEntity obj, string name) { 
  return obj.name == name;
 }, 
 " special"
);

I am using LinkqKit here to try to make this work but I get the error "unable to cast FieldExpression to LambdaExpression."

My first question is: is there a better/simpler way to make this happen? Am I complicating this too much? Do I even need to use LinqKit?

Second: how can I get past this error?

Riz
  • 6,486
  • 19
  • 66
  • 106
  • Why do you think `delegate(SomeEntity obj, string name) { return obj.name == name; }, " special" );` is easier than writing `obj => obj.Name == " special"`? – Servy Jan 15 '18 at 22:19
  • 1
    This kind of feels like an X/Y problem to me. Can you go in to more detail about why you think you need this functionality? – Bradley Uffner Jan 15 '18 at 22:29
  • I think that such functionalty already exists: `dbContext.SomeEntities.Where(e => e.Name == "special")`? – Hemid Abbasov Jan 15 '18 at 23:24
  • because I don't want object.Name == " special". " special" is going to get formatted or cleaned up somehow in a specified lookup function and then going to get passed into the supplied expression. Also the lookup function will do other logic based on whether the object was found. I just don't want to duplicate this functionality for each entity in question, hence creating it for a generic entity. – Riz Jan 16 '18 at 01:15
  • @Riz Then all you need is a string variable, rather than a string literal, and you still have no need for expression manipulation or for this function that's adding zero value. – Servy Jan 16 '18 at 14:08

1 Answers1

0

It's almost like you are using linq to rewrite linq extensions. It would be helpful like said above if you have an X and Y scenario written out and what you would hope this to achieve. I know personally I have used expression when I wanted something like:

private List<TEntity> GetEntities<TEntity>(Expression<Func<TEntity, bool>> 
predicate = null) where TEntity : class
{
    using (var context = new ExpensesEntities())
    {
        IQueryable<TEntity> data = context.Set<TEntity>();
        if (predicate != null)
        {
            data = data.Where(predicate);
        }

        return data.ToList();
     }
 }

I used this when I had a repository pattern where I had two different tables(lots more in real example). Where I wanted to wrap the context part up to auto invoke the dispose for me (the using(var context = new Context())) and just deal with the meat of the problem. Which is essentially which table it is and what property I want to run a predicate on. So in the example below would be how I would call this for just all of a table and then for another table to add a predicate to it on the property of TypeId.

public List<X> GetCategories() => GetEntities<X>();
public List<Y> GetTypes() => GetEntities<Y>(x => x.TypeID != 3);
djangojazz
  • 14,131
  • 10
  • 56
  • 94