Using a table I had handy (as you provided no schema), using 5 as a placeholder for an actual variable in LINQPad:
var pabove = (from p in PolicyStatuses
where p.PolicyStatusID >= 5
orderby p.PolicyStatusID ascending
select p).Take(2);
var pbelow = (from p in PolicyStatuses
where p.PolicyStatusID <= 5
orderby p.PolicyStatusID descending
select p).Take(2);
pabove.Union(pbelow).Dump();
This will grab one above and one below. Note however that returning null doesn't happen here when you don't find a row above or below, it simply excludes such results. If you actually care, you can take the count of pabove and pbelow to detect if such a record was found.
The result (obviously again from my schema):
IOrderedQueryable<PolicyStatus> (3 items)
PolicyStatusID Status RecordCreated
4
Unknown
8/26/2007 11:06:11 PM
5
Expired
8/26/2007 11:06:11 PM
6
Cancelled
8/26/2007 11:06:11 PM
Note that 4, 5 and 6 were found. This has an advantage over loading the entire table and then picking the results near the one you want. Using Take(2) only 3 records should go across the wire from your SQL server to you web server. If your table is small enough, simply query the table with a sort and filter what you need.
Here is the SQL produced by LINQ (some fields omitted):
SELECT [t2].[PolicyStatusID], [t2].[Status], [t2].[RecordCreated]
FROM (
SELECT TOP (2) [t0].[PolicyStatusID], [t0].[Status], [t0].[RecordCreated]
FROM [PolicyStatus] AS [t0]
WHERE [t0].[PolicyStatusID] >= @p0
ORDER BY [t0].[PolicyStatusID]
UNION
SELECT TOP (2) [t1].[PolicyStatusID], [t1].[Status], [t1].[RecordCreated]
FROM [PolicyStatus] AS [t1]
WHERE [t1].[PolicyStatusID] <= @p1
ORDER BY [t1].[PolicyStatusID] DESC
) AS [t2]