atconway
atconway

Reputation: 21304

LINQ Query Issues when trying to select from empty collection

I have the following LINQ query that is pulling a final resultset from 2 collections: usersAd and usersWithSecurity:

var results = from usrAd in usersAd
              from usrRepo in usersWithSecurity
                             .Where(x => usrAd.Value.ToLower() == x.Value.ToLower())
                             .DefaultIfEmpty()
      select new User(userRepository)
      {
        ID = usrRepo == null ? null : usrRepo.ID,
        Value = usrAd.Value,
        FullName = usrAd.FullName
      };

The problem is I keep getting the following error: Value cannot be null.

I know the issue is that the usersWithSecurity collection is empty. I added the '.DefaultIfEmpty()` on the end but it still produces the exception.

How can I modify my LINQ statement to go ahead and return everything from usersAd and items from usersWithSecurity if it exists and the values match (as shown in the lambda)?

Upvotes: 5

Views: 5478

Answers (3)

Christopher Currens
Christopher Currens

Reputation: 30695

I believe that Value cannot be null is the standard message from an ArgumentNullException. If you're debugging, and you expand on the error message, you'll see the actual parameter name that is causing the argument null exception.

Are any of usersAd, usersWithSecurity, userRepository null?

EDIT:

Okay, with more information provided from you in your comment, I now see the issue. usersWithSecurity is null, and it can't be. The source parameter is the name for the source IEnumerable or IQueryable in all of the extension methods found in the Enumerable and Queryable classes.

If you fix that, it should work as you expect, left join and all.

usersWithSecurity = usersWithSecurity ?? Enumerable.Empty<User>(); // or similar

Upvotes: 2

J&#228;mes
J&#228;mes

Reputation: 7245

Your issue certainly occurs when you are performing your .ToLower() on an empty var. I recommend to avoid hidden string allocations within a loop (in your case, within your Where). Instead, use String.Compare().

Here is an example using your code.

var results = from usrAd in usersAd
      from usrRepo in usersWithSecurity.Where(x => string.Equals(usrAd.Value, x.Value, StringComparison.OrdinalIgnoreCase))
      select new User(userRepository)
      {
        ID = usrRepo == null ? null : usrRepo.ID,
        Value = usrAd.Value,
        FullName = usrAd.FullName
      };

Upvotes: 1

hunter
hunter

Reputation: 63522

var usersWithSecurity = _biz.getUsersWithSecurity() ?? new List<User>();

var results = from usrAd in usersAd
              from usrRepo in usersWithSecurity
              where usrAd.Value.ToLower() == usrRepo.Value.ToLower()
              select new User(userRepository)
              {
                  ID = usrRepo == null ? null : usrRepo.ID,
                  Value = usrAd.Value,
                  FullName = usrAd.FullName
              };

Upvotes: 2

Related Questions