I understand your idea. I wrote this extensions method for implement.
But it need to optimize because abuse LinQ may impact performance.
public static IEnumerable<T> TakeDistinct<T, TProperty>(this IEnumerable<T> source, int take, Expression<Func<T, TProperty>> distinctBy)
{
var orderList = source.AsQueryable().GroupBy(distinctBy).OrderBy(x=>x.Key).Take(take).Select(x=>x.Key).ToList();
var mappingFunc = distinctBy.Compile();
return source.Where(x => orderList.Contains(mappingFunc.Invoke(x)));
}
static void Main()
{
var jobLines = @"10 start
10 progress
10 alert
10 done
12 start
12 error
12 done
32 start
32 info
32 done";
var jobs = jobLines.Split('\n').Select(line =>
{
var splited = line.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
return new JobItem
{
Job = Convert.ToInt32(splited[0]),
Status = splited[1]
};
});
var newJobs = jobs.TakeDistinct(2, x => x.Job);
foreach (var job in newJobs)
{
Console.WriteLine($"{job.Job} - {job.Status}");
}
Console.ReadLine();
}
class JobItem
{
public int Job { get; set; }
public string Status { get; set; }
}
public static IEnumerable<T> TakeDistinct<T, TProperty>(this IEnumerable<T> source, int take, Expression<Func<T, TProperty>> distinctBy)
{
var orderList = source.AsQueryable().GroupBy(distinctBy).OrderBy(x=>x.Key).Take(take).Select(x=>x.Key).ToList();
var mappingFunc = distinctBy.Compile();
return source.Where(x => orderList.Contains(mappingFunc.Invoke(x)));
}

--- UPDATED----
This update is to support LinQ to SQL
public static IQueryable<T> TakeDistinct<T, TProperty>(this IQueryable<T> source, int take, Expression<Func<T, TProperty>> distinctBy)
{
var orderList = source.AsQueryable().GroupBy(distinctBy).OrderBy(x => x.Key).Take(take).SelectMany(x => x);
return orderList;
}
--- UPDATED ----
I add generated SQL from statement above.
I've created fake table name JobItems
with Columns: Id
, Job
and Status
SELECT
[Extent2].[Id] AS [Id],
[Extent2].[Job] AS [Job],
[Extent2].[Status] AS [Status]
FROM (SELECT TOP (2) [Distinct1].[Job] AS [Job]
FROM ( SELECT DISTINCT
[Extent1].[Job] AS [Job]
FROM [dbo].[JobItems] AS [Extent1]
) AS [Distinct1]
ORDER BY [Distinct1].[Job] ASC ) AS [Limit1]
INNER JOIN [dbo].[JobItems] AS [Extent2] ON [Limit1].[Job] = [Extent2].[Job]