1

Here is my code. Can anyone help me refactor this piece of code. i'm trying to use field name as variable so I wouldn't have to use switch case. Something like from dr in db.Users where dr.FieldName.Contains(value).

public static List<User> GetUser(string value, string fieldName)
{
    var db = new CCPTDataContext();
    var users = new List<User>();

    switch (fieldName)
    {
        case "FirstName":
            users = (from dr in db.Users where dr.FirstName.Contains(value)
                     select new User
                     {
                         Username = dr.Username,
                         FirstName = dr.FirstName,
                         LastName = dr.LastName
                     }).ToList();

            break;
        case "LastName":
            users = (from dr in db.Users where dr.LastName.Contains(value)
                     select new User
                     {
                         Username = dr.Username,
                         FirstName = dr.FirstName,
                         LastName = dr.LastName
                     }).ToList();
            break;
    }
    return users;
}
puretppc
  • 3,232
  • 8
  • 38
  • 65
Ali
  • 478
  • 4
  • 10

2 Answers2

4

You have to create the Expression Tree manually using classes from System.Linq.Expression namespace:

public static Expression<Func<TSource, bool>> GetPropertyContainsValueExpression<TSource>(string propertyName, string value)
{
    var param = Expression.Parameter(typeof(TSource), "x");
    var prop = Expression.Property(param, propertyName);
    var valueExp = Expression.Constant(value, typeof(string));
    var contains = Expression.Call(prop, "Contains", null, valueExp);
    return Expression.Lambda<Func<TSource, bool>>(contains, param);
}

then you can use it like that:

public static List<User> GetUser(string value, string fieldName)
{
    var db = new CCPTDataContext();

    return db.Users.Where(GetPropertyContainsValueExpression<User>(fieldName, value)).ToList();
}
MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • Some providers (I think EF 5) might not correctly parameterize the query in the above snippet. In order to get the parameterized queries, what I do is wrap the value in a `Tuple` and get the `Item1` property: `var container = new Tuple(value); var containerExpression = Expression.Constant(container, typeof(Tuple)); var valueExp = Expression.Property(containerExpression, "Item1");` – felipe Jan 16 '14 at 19:25
  • @Kosar you're welcome! You should consider marking the answer as accepted if it solved your problem. That's how SO works! – MarcinJuraszek Jan 16 '14 at 21:53
  • @Marcin, I tried to mark as accepted, couldn't find any link, button or something like that for it. Can you guide me how to do that. – Ali Jan 21 '14 at 05:23
  • @Kosar Right below post score the should be gray mark you can click. Here is a great question about that: http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – MarcinJuraszek Jan 21 '14 at 05:30
0

This should work:

users = (from dr in db.Users 
where (fieldName.Equals("FirstName") && dr.FirstName.Contains(value))
      || (fieldName.Equals("LastName") && dr.LastName.Contains(value))
                 select new User
                 {
                     Username = dr.Username,
                     FirstName = dr.FirstName,
                     LastName = dr.LastName
                 }).ToList();
Obi
  • 3,091
  • 4
  • 34
  • 56