views:

34

answers:

2

My main entity is called [Contract]. Contract has a many 2 many relationship w/ [Service].

When I query for a list of Contracts I grab the 1st Service available like this:

IQueryable<Contract> q = ctx.Contracts.Skip(startRow - 1).Take(pgSize);
q.Select(c =>
         new ContractSearchResult()
         {
           ContractID = c.ContractID,
           FirstService = c.Contract2Service.FirstOrDefault().Service.Name,
           ServiceCount = c.Contract2Service.Count,
         }
        ).ToList();

(When I display this list I show the FirstService if there's only 1. If > 1 I show "My1stService (3)" to show I'm seeing the 1st of 3 services) This works fine.

My question is this:

Is there any way to sort by FirstService? Or is this impossible? I haven't found a way of expressing this in linq and allow for paging.

Any help would be appreciated.

+2  A: 

You need to OrderBy before you page.

var result = ctx.Contracts
    .Select(c =>
        new ContractSearchResult()
        {
            ContractID = c.ContractID,
            FirstService = c.Contract2Service.FirstOrDefault().Service.Name,
            ServiceCount = c.Contract2Service.Count,
        })
 .OrderBy(x => x.FirstService)
 .Skip(startRow - 1)
 .Take(pgSize)
 .ToList();

Also note that FirstOrDefault can return null and you should check for that. If you know that it will (or should) never be null then use First instead.

Mark Byers
I updated the code to show a bit more. You are right, that's the problem. I'm doing paging and don't have x.FirstService to refer to before the select takes place.
@user169867: You have to move the paging to the end.
Mark Byers
If that were done, would the paging still occur on the DB or would all the records be returned and then filtered?
It would probably still be in the database. You can view the SQL query that is sent to the database and check for yourself. You can see the SQL in the debugger or in the log.
Mark Byers
Really? That could be very useful. How do you see the SQL in the debuger?
+1  A: 
q.OrderBy(c => c.Contract2Service.FirstOrDefault().Service.Name)
 .Select(c =>
        new ContractSearchResult()
        {
            ContractID = c.ContractID,
            FirstService = c.Contract2Service.FirstOrDefault().Service.Name,
            ServiceCount = c.Contract2Service.Count,
        }
    )
 .ToList();

Unless I'm missing something in your question (which is possible), it should be as simple as calling OrderBy() after your call to Select()

Justin Niessner
Yes, what complicates it though is that the sort should happen before the select so the paging will work correctly.
@user I updated the answer so that the sorting happens prior to the select.
Justin Niessner
I see, I think that may work. Do you by chance know a way of doing that OrderBy operation as a "Dynamic Linq" string?
Unfortunately I don't. Sorry.
Justin Niessner
This doesn't work. The paging is still done before the order by.
Mark Byers
Yes, true. It must go OrderBy, paging, then select. But the orderby predicate is correct.