Paolo B
Paolo B

Reputation: 3354

Select each int in array

I have the following Linq query which is working fine.

var results = accounts.Select(a => new
{
    Id = a.Id,
    Scores = _context.AccountAttributeStatistics.Where(at => at.AccountId == a.Id 
                             && at.LatestVersion && at.AttributeId == 39)
        .Select(at => new
        {
            Id = at.AttributeId,
            Percentile = at.Percentile,
            Percentage = at.CurrentPercentage,
        }).ToList()
 });

However I now need to run this for a number if different AttributeIds. I have tried:

Scores = _context.AccountAttributeStatistics.Where(at => at.AccountId == a.Id 
                 && at.LatestVersion && at.AttributeId == 39 || at.AttributeId == 40 
                 || at.AttributeId == 41 || at.AttributeId == 42)

Unfortunately this seems to ignore the at.LatestVersion and returns all scores instead of the latest for these attributes.

What is the best way to get the desires results?

I have thought to use an array and use a foreach but not sure how this would work?

int[] attributeIds = {39, 40, 41, 42, 43};

Scores = _context.AccountAttributeStatistics.Where(at => at.AccountId == a.Id 
                 && at.LatestVersion && at.AttributeId == attributeIds.ForEach(x => x))

But get the error Only assignment, call, increment, decrement, and new object expressions can be used as a statement

Not sure if that would be the correct way, using linq, to achieve this anyway?

Upvotes: 1

Views: 236

Answers (4)

Mittal Patel
Mittal Patel

Reputation: 2762

You need to add brackets for that. As you have used the || OR, so it takes all the records having the attributes 40, 41,42 without checking the latest one.

 Scores = _context.AccountAttributeStatistics.Where(at => (at.AccountId == a.Id 
             && at.LatestVersion) && (at.AttributeId == 39 || at.AttributeId == 40 
             || at.AttributeId == 41 || at.AttributeId == 42))

Either use:

 int[] attributeIds = {39,40,41,42};
 Scores = _context.AccountAttributeStatistics.Where(at => (at.AccountId == a.Id 
             && at.LatestVersion) && attributeIds.Contains(at.AttributeId))

Upvotes: 3

Tim Schmelter
Tim Schmelter

Reputation: 460068

In your query brackets were missing so that LatestVersion is included always. But i would use a collection for the allowed AttributeIds and use Enumerable.Contains:

int[] attributeIds = {39, 40, 41, 42, 43};

....
Scores = _context.AccountAttributeStatistics
    .Where(at => at.AccountId == a.Id 
              && at.LatestVersion 
              && attributeIds.Contains(at.AttributeId))
....

Upvotes: 3

Alex
Alex

Reputation: 796

Just a few additional parentheses would solve your problem:

Scores = _context.AccountAttributeStatistics.Where(at => at.AccountId == a.Id 
                     && at.LatestVersion && (at.AttributeId == 39 || at.AttributeId == 40 
                     || at.AttributeId == 41 || at.AttributeId == 42))

Upvotes: 1

John Woo
John Woo

Reputation: 263703

You can use Contains(). This is the same as IN in sql.

.Where(at => at.AccountId == a.Id 
             && at.LatestVersion 
             && attributeIds.Contains(at.AttributeId))

Upvotes: 1

Related Questions