HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Get values between two dates

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
datestwogetbetweenvalues

Problem

I have a search form where users can enter ValidFrom and ValidTo dates,

There are three conditions:

-
ValidFrom and ValidTo NOT NULL

Action: Get values between two dates

-
ValidFrom is NOTNULL and ValidTo is NULL

Action: Get values where date is greater than ValidFrom

-
ValidFROM is NULL and ValidTo is NOTNULL

Action: get values where date is less than ValidTo

This is what I have got:

if (model.ValidFrom != null && model.ValidTo != null)
        {
            var dateFrom = (DateTime)model.ValidFrom;
            var dateTo = (DateTime)model.ValidTo;
            dalList = dalList.Where(s =>
                DbFunctions.TruncateTime(s.ValidFrom) >= dateFrom.Date
                && DbFunctions.TruncateTime(s.ValidTo)  DbFunctions.TruncateTime(s.ValidFrom) >= dateFrom.Date).AsQueryable();
        }
        if (model.ValidFrom == null && model.ValidTo != null)
        {
            var dateTo = (DateTime)model.ValidTo;
            dalList = dalList.Where(s => DbFunctions.TruncateTime(s.ValidTo) <= dateTo.Date).AsQueryable();
        }


Is there a better way to write this type of search?

Solution

Although the answer from Heslacher is a really good one, here's also what you might do. Create two boolean variable to check for null on the model.ValidFrom and model.ValidTo:

bool modelValidFromIsNull = model.ValidFrom == null;
bool modelValidToIsNull = model.ValidTo == null;


Now, like Heslacher mentioned, place a guard to rule out if they are both null.

if (modelValidFromIsNull && modelValidToIsNull) { return null; }


Now you can use these bool variables to do some magic. In the Where() clause of the query, use these flags to check or ignore the condition you want to apply. If the flag is true, the condition will be skipped and if it is false, the condition will be evaluated. A small example:

var numbers = new[] { 1, 2, 3, 4, 5, 6 };
var remaining = numbers.Where(x => false || x > 3);


The variable remaining will now contain 4, 5 and 6. If you were to change that false to true, the variable remaining would contain all the numbers from the original source. [That's why you need the guard :) ]

Now you can apply this logic to your code. When the model.ValidFrom is not null, your variable modelValidFromIsNull will be false. This means that in the where clause the left part is false and the second part will be evaluated. The same goes for model.ValidTo.

This is the resulting code:

bool modelValidFromIsNull = model.ValidFrom == null;
bool modelValidToIsNull = model.ValidTo == null;

if (modelValidFromIsNull && modelValidToIsNull) { return null; }

var result = dalList.Where(s => modelValidFromIsNull || DbFunctions.TruncateTime(s.ValidFrom) >= dateFrom.Date)
                    .Where(s => modelValidToIsNull || DbFunctions.TruncateTime(s.ValidTo) <= dateTo.Date);

Code Snippets

bool modelValidFromIsNull = model.ValidFrom == null;
bool modelValidToIsNull = model.ValidTo == null;
if (modelValidFromIsNull && modelValidToIsNull) { return null; }
var numbers = new[] { 1, 2, 3, 4, 5, 6 };
var remaining = numbers.Where(x => false || x > 3);
bool modelValidFromIsNull = model.ValidFrom == null;
bool modelValidToIsNull = model.ValidTo == null;

if (modelValidFromIsNull && modelValidToIsNull) { return null; }

var result = dalList.Where(s => modelValidFromIsNull || DbFunctions.TruncateTime(s.ValidFrom) >= dateFrom.Date)
                    .Where(s => modelValidToIsNull || DbFunctions.TruncateTime(s.ValidTo) <= dateTo.Date);

Context

StackExchange Code Review Q#78313, answer score: 7

Revisions (0)

No revisions yet.