Speaking of Select

So like Where and other fine Extension methods, Select allows you to either give it a lambda expression like so:

  List<String> newList = userList.Select(user => user.Name);

Or

  List<Int32> newList = userList.Select(user => user.ID);

So either you get a list of Names or IDs. What the hell do you care? Well if you are capable of breathing, you should also notice that one list is a list of strings the other a list of integers. What if you wanted a generic select method? Well for starters you would do something like this:

public List<String> SelectFromUserList(Func<User, String> selectMethod, List<User> userList)
{
  return userList.Select(selectMethod).ToList();
}

Where the select method for a user name would be something like this:

  List<String> nameList = SelectFromUserList(currentUser => currentUser.UserName, userList);

Sweet… oh wait, that only works if I want a list strings. Great if I wanted LastName, FirstName, ect but sucks if I wanted an integer ID.

  List<String> nameList = SelectFromUserList(currentUser => currentUser.UserID, userList); //BOOM

But wait, you can do that!

public List<K> SelectUserNameList<K>(Func<User, K> selectMethod, List<User> userList)
{
  return userList.Select(selectMethod).ToList();
}

Aw snap, now I can get a list of anything I want, well at least a one type, one dimensional array. By the way, this is the first step in probably a series of posts that will end up with a much cleaner way of doing this.

Like versus Contains in Linq

So have to figure this one out. Say you have:

private static Expression<Func<User, Boolean>> WhereLikeFirstNameLastNameUserName(String name)
{
  return currentUser => SqlMethods.Like(currentUser.UserName, "%" + name + "%")
  || SqlMethods.Like(currentUser.FirstName, "%" + name + "%")
  || SqlMethods.Like(currentUser.LastName, "%" + name + "%");
}

And

private static Expression <Func<User, Boolean>> WhereLikeFirstNameLastNameUserNameWithoutLike(String name)
{
  return currentUser => currentUser.UserName.Contains(name)
  || currentUser.FirstName.Contains(name)
  || currentUser.LastName.Contains(name);
}

The first one should look familiar, its part of the “dynamic” linq stuff I’ve been posting. Now guess which one gives me this SQL when profiled:

exec sp_executesql N
'SELECT
 [t0].[UserID],
 [t0].[FirstName],
 [t0].[LastName],
 [t0].[Password],
 [t0].[UserName],
 [t0].[UserTypeID]
FROM
 [dbo].[User] AS [t0]
WHERE
 ([t0].[UserName] LIKE @p0)
OR
 ([t0].[FirstName] LIKE @p1)
OR
 ([t0].[LastName] LIKE @p2)
ORDER BY
 [t0].[UserName]',

N'@p0 varchar(3),
 @p1 nvarchar(3),
 @p2 nvarchar(3)',
 @p0='%s%',
 @p1=N'%s%',
 @p2=N'%s%'

If you answered both, you are correct or you looked ahead for the answer and therefore are a tool. Now which do you think that…

query.ToList()

Produces the correct list? If you answered Contains, then you are correct again. If you are a tool, you probably looked ahead again…

Why is this? I HAVE NO IDEA… Something I have to look into for sure.