Reputation: 678
I have a list of DateRange objects, which have StartDate and EndDate properties. I need to select all the rows from a table in my database which have a DateTime field that falls within any of those DateRanges. So I'd like to do something like this:
// Using an IQueryable<DateRange> called dateRanges
var tests = from test in dbContext.Tests
where dateRanges.Any(range => range.StartDate <= test.Date && range.EndDate >= test.Date)
select test
This gives me an error because DateRange is not a primitive type and so LINQ to SQL can't use it. Is there any other way to do what I'm trying to do here? Been googling and trying different things for a couple hours, I feel like I'm very close but can't quite get there. Thanks in advance.
Upvotes: 0
Views: 2263
Reputation: 678
The way I decided to do this in order to guarantee that no unnecessary data was being transferred was to create a stored procedure called GetTestsInDateRange on my database which takes in a start and end date and returns all of the tests that are in that range. Then in my code I'm looping through my list of DateRanges, calling the stored procedure once for each DateRange, and unioning the results together.
IEnumerable<Test> tests = new List<Test>();
foreach (DateRange range in selectedDateRanges)
{
tests = tests.Union(dbContext.GetTestsInDateRange(range.StartDate, range.EndDate));
}
Whether that's the ideal solution or not I don't know (probably depends on how many DateRanges were selected and therefore how many separate calls it's making to the database), but it's working well for my scenario.
Upvotes: 0
Reputation: 2973
Try to use Linq2Sql with dynamic query like
(p => value1.StartDate <= p.Date && value1.EndDate >= p.Date) || (p => value2.StartDate <= p.Date && value2.EndDate >= p.Date)
Example: Linq2SQL "or/and" operators (ANDed / ORed conditions)
Upvotes: 0
Reputation: 152566
Other that crafting your own SQL statement by concatenating the criteria for each range, one way to partially limit the results that you get back would be to use the min and max dates of the ranges, then filtering further in Linq-To-Objects:
var minStartDate = dateRanges.Min(r => r.StartDate);
var maxEndDate = dateRanges.Max(r => r.EndDate);
var tests = (from test in dbContext.Tests
where minStartDate <= test.Date && maxEndDate >= test.Date
select test)
.AsEnumerable() // change to Linq-To-Objects
.Where(test => dateRanges.Any(range => range.StartDate <= test.Date
&& range.EndDate >= test.Date));
This would work perfectly for one range, and would be only marginally worse unless your ranges had huge gaps in between them.
Upvotes: -1