1

I'm trying to optimize the following routine so that it only uses one database query instead of multiple but the filter (loop conditions) don't seem to be applied as all messeges are fetched.

     public async Task<List<Message>> GetInboxMessegesFromUser(string inboxUser, List<string> senders)
     {
             // Doesn't work

            var query = from m in _context.Messeges where m.ToUser == inboxUser select m;
            foreach (string sender in senders)
            {
                query.Where(m => m.FromUser == sender);
            }
            return await query.ToListAsync();

            // Old code 

            List<Message> messeges = new List<Message>();
            foreach (string sender in senders)
            {
                messeges.AddRange(await _context.Messeges.Where(m => m.FromUser == sender && m.ToUser == inboxUser).ToListAsync());
            }


               return messeges;
            }

How to add a dynamic number of conditions to a LINQ query before executing it so that a O(N*M) turns into O(N) ?

3
  • 1
    replace: query = query.Where(m => m.FromUser == sender); Commented Oct 17, 2019 at 14:28
  • Also, this will be more effecient in your scenario instead of the foreach: stackoverflow.com/questions/10667675/… Commented Oct 17, 2019 at 14:29
  • 1
    That query will not produce any results due to a logic error even after you do the assignment query = query.Where(....);. You cant have a record that has more than 1 value on a property. So if you pass in 2 values in the senders List any one record will never be both of those values. The result is that this method will always return an empty list. Commented Oct 17, 2019 at 14:31

2 Answers 2

2

That query will not produce any results due to a logic error even after you do the assignment query = query.Where(....);. You cant have a record that has more than 1 value on a property. So if you pass in 2 values in the senders List any one record will never be both of those values. The result is that this method will always return an empty list.

You can use .Contains to see if there is at least one match from a list which would translate to an IN clause in Sql Server.

Your whole method could be rewritten like this:

public Task<List<Message>> GetInboxMessegesFromUser(string inboxUser, List<string> senders)
{
    return _context.Messeges
        .Where(message => message.ToUser == inboxUser && senders.Contains(message.FromUser))
        .ToListAsync();
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is correct, but I have a hard time condoning using underscore as a variable name.
To elaborate: underscores were arguably a bad variable name regardless, but with C# 7, Discards reinforced the notion that an underscore is a placeholder for something you don't actually intend to use. See learn.microsoft.com/en-us/dotnet/csharp/discards
1

Try changing the existing code to:

messeges.AddRange(await _context.Messeges.Where(m => senders.Contains(m.FromUser) && m.ToUser == inboxUser).ToListAsync());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.