Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use null-coalescing operator with nullable date

My view model has a nullable date property such as...

[DataType(DataType.Date)]
public DateTime? SanctionExpires { get; set; }

But when I try to use the null-coalescing operator such as...

var test = model.SanctionExpires.Value.ToUniversalTime() ?? model.SanctionExpires;

I get the following error...

operator '??' cannot be applied to operands of type 'datetime' and 'datetime'

I thought this should work because I set my date property to nullable and this post suggests it should work too. What am I doing wrong?

UPDATE

To give more clarity I want to use null-coaslescing to assign a Dapper parameter which will update a DateTime field in my database. The field can accept null values or datetime values. Basically if a user specifies a date then assign the provided date to the parameter otherwise assign null...

p.Add("@SanctionExpires", model.SanctionExpires.Value.ToUniversalTime() ?? model.SanctionExpires);

Note that I have to do the UTC conversion because i'm using SQL Azure which uses UTC for dates otherwise my time is out by 11 hours (i'm in Australia) if i just pass a data from my local system. In sql i'm using a function to offset the date to my timezone before updating the table.

My current solution to get it working is below but not sure if this is the cleanest way. Would be nice to get in one line...

if (model.SanctionExpires == null)
    p.Add("@SanctionExpires", model.SanctionExpires);
else
    p.Add("@SanctionExpires", model.SanctionExpires.Value.ToUniversalTime());
like image 365
OjM Avatar asked Nov 24 '16 13:11

OjM


People also ask

What is nullable coalescing operator?

The nullish coalescing operator ( ?? ) is a logical operator that returns its right-hand side operand when its left-hand side operand is null or undefined , and otherwise returns its left-hand side operand.

Can DateTime be nullable?

DateTime CAN be compared to null; It cannot hold null value, thus the comparison will always be false. DateTime is a "Value Type". Basically a "value type" can't set to NULL. But by making them to "Nullable" type, We can set to null.

What is nullable types and null-coalescing operator in C#?

Nullable types work as a connector between a database and C# code to provide a way to transform the nulls to be used in C# code. Null Coalescing operators simplify the way to check for nulls and shorten the C# code when the developer is dealing with nulls.

What is null conditional and null coalescing?

In cases where a statement could return null, the null-coalescing operator can be used to ensure a reasonable value gets returned. This code returns the name of an item or the default name if the item is null. As you can see, this operator is a handy tool when working with the null-conditional operator.


2 Answers

.Value on a nullable assumes it can't be null. Hence is applying the null-coalescing operator on it useless and forbidden.

You could use the operator like this, but going on your code I am not sure if this is what you need:

DateTime test = (model.SanctionExpires ?? DateTime.Now).ToUniversalTime();

For your update: you can shortcut that evaluation like this:

DateTime? test = model.SanctionExpires?.ToUniversalTime();
like image 174
Patrick Hofman Avatar answered Nov 06 '22 01:11

Patrick Hofman


You can also use the GetValueOrDefault method to return default value if your DateTime object is null. In case you want to use the actual date, you should use DateTime.Now.

For example following code snippet can help you:

var defaultDateTime = DateTime.Now;
var dateTime = model.SanctionExpires.GetValueOrDefault(defaultDateTime).ToUniversalTime();

If you call GetValueOrDefault without params it will use default(DateTime) if your DateTime is null

var dateTime = model.SanctionExpires.GetValueOrDefault().ToUniversalTime(); //dateTime == default(DateTime) in case !model.SanctionExpires.HasValue

Update

If you are using C#5.0 or below you can use following code snippet because NULL conditional operator is available not before C#6.0.

p.Add("@SanctionExpires", !model.SanctionExpires.HasValue ? null : (DateTime?)model.SanctionExpires.Value.ToUniversalTime());
like image 26
Dominik Herold Avatar answered Nov 06 '22 01:11

Dominik Herold