tags:

views:

26

answers:

1

I have a LINQ statement like this:

var media = (from p in postService.GetMedia(postId)
             select new
             {
                 PostId = postId,
                 SynthId = p.SynthId
             });

There are many(possibly thousands) of records returned with the same SynthId. I want to select one one, any random one. So when I'm finished, media should contain records with distinct SynthId.

SynthId can be null, I want all nulls to be in media (the distinct should not affect them). My DAL is EntityFramework, if that will help.

How do I accomplish this in the most efficient way?

+2  A: 

Use a grouping query:

var media =
    from p in postService.GetMedia(postId)
    group p by p.SynthId into g
    select g.First();

This will give you the first post in the sequence for each group of records, where the grouping key is the SynthId.

If it's important for you to do a projection (i.e. to use select new { ... }) then you should be able to use the let keyword:

var media =
    from p in postService.GetMedia(postId)
    group p by p.SynthId into g
    let firstPost = g.First()
    select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId };

If you want all null values for SynthId to be in their own group, then I would probably filter the first list and then do a concatenation, i.e.:

var media = postService.GetMedia(postId);
var myMedia =
    (from p in media
     where p.SynthId != null
     group p by p.SynthId into g
     let firstPost = g.First()
     select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId })
    .Concat
    (from p in media
     where p.SynthId == null
     select new { PostId = firstPost.PostId, SynthId = firstPost.SynthId });
Aaronaught
That worked, but the grouping also affected the null SynthId. Is there a way to make exceptions on null, or any content for that matter?
Shawn Mclean
@Shawn: What do you mean it "affected the null?" What was the expected vs. actual result?
Aaronaught
SynthId can be null. I dont want those to be grouped. So if there were 10 null SynthId records, 5 records with the same SynthId. There should be 11 records returned. All the null records with null SynthId and the 1 grouped.
Shawn Mclean
Thank you. In the background, thats two seperate O(n) loops?
Shawn Mclean
@Shawn: It's only O(n) if `postService.GetMedia` returns a materialized in-memory collection like a `List<Post>`. If the query is translated to the database and the `SynthId` column is indexed then it will be significantly faster than that (bound only by the number of results, not the total number of entries in the database).
Aaronaught