0
 List<APList> List = new List<APList>() --

List = statement.APList.Where(f => f.PeriodKey == periodkey
                                 && f.ClassKey == classkey
                                 && f.ClassKey != null)
                        .GroupBy(g => new { g.PostKey})
                        .Select(s => s.First()).ToList();

foreach (var item in List)
{
    item.ClassKey = null;
} 

--data 

periodkey(int)  postkey(int)   classkey(int?)       
101          12        10
100          12        11
101          11        10
100          11        11




--expected 

periodkey  postkey   classkey       
101          12        null
100          11        null

This is working but i dont want to use foreach loop .Is there a better way to optimize the query and write it in a single linq query using Lambda expressions.

Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27
user3920526
  • 404
  • 4
  • 20

3 Answers3

0

You can simply select classKey as null

List = statement.APList.Where(f => f.PeriodKey == periodkey
                                 && f.ClassKey == classkey
                                 && f.ClassKey != null)
                        .GroupBy(g => new { g.PostKey})
                        .Select(s => s.First())
                        .Select(i => new APList() {
                            PeriodKey = i.PeriodKey,
                            ClassKey = null,
                            /* ... */
                        })                            
                        .ToList();
Marco
  • 22,856
  • 9
  • 75
  • 124
0

As per the answers on (Assigning values inside a LINQ Select?), a foreach loop (or .ForEach) is better than using LINQ because LINQ is meant for querying objects, not mutating them.

If you do want to replace the loop, you could instead use

List = statement.APList.Where(f => f.PeriodKey == periodkey
                             && f.ClassKey == classkey
                             && f.ClassKey != null)
                       .GroupBy(g => new { g.PostKey})
                       .Select(s => s.First())
                       .ToList();

List.ForEach(i => i.ClassKey = null);

The .ForEach must be on a separate line because it performs an action for each item in List and returns void, not the list of items.

yinnonsanders
  • 1,831
  • 11
  • 28
0

You can just group them by period- and postkeys

var result = statement.APList.Where(ap => ap.PeriodKey == periodkey)
                             .Where(ap => ap.ClassKey == classkey)
                             .Where(ap => ap.ClassKey != null)
                     .GroupBy(ap => new { ap.PeriodKey, ap.PostKey })
                     .Select(group => group.Key);

Now result contains anonymous objects of unique periodKey and postKey.
You can use them to not mixed it with already existed class which contains classKey.

Or if you still want use already existed object then create new instance of this class with classKey set to null

var finalResult = result.Select(group => new AP 
                                { 
                                    PeriodKey = group.PeriodKey,
                                    PostKey = group.PostKey
                                })
                        .ToList();

Using .ForEach extension method will not be optimizing because it will do same foreach loop, as other Linq extension methods.

Fabio
  • 31,528
  • 4
  • 33
  • 72