Beware - NULL Values Can Trip You Up When Using Dapper
[C#, .NET, Database, StarLibrary, Dapper, Beware]
I have extensively discussed the use of the excellent library Dapper for database access with most database engines.
Today we will look at a potential problem you can run into unless you understand how to use nullable value types.
Take a common scenario where you need to retrieve the time in the database server.
The code is as simple at this:
using (var cn = new SqlConnection("data source=;;uid=sa;pwd=YourStrongPassword123;TrustServerCertificate=true"))
{
var date = cn.QuerySingle<DateTime>("SELECT GetDate()");
Console.WriteLine(date);
}
This will print the following:
03/06/2026 22:08:25
Now suppose the query returned a NULL
using (var cn = new SqlConnection("data source=;;uid=sa;pwd=YourStrongPassword123;TrustServerCertificate=true"))
{
var date = cn.QuerySingle<DateTime>("SELECT NULL");
Console.WriteLine(date);
}
This will throw an exception.
Unhandled exception. System.Data.DataException: Error parsing column 0 ((Unnamed Column)=n/a - Null object cannot be converted to a value type.)
---> System.InvalidCastException: Null object cannot be converted to a value type.
at System.Convert.ChangeType(Object value, Type conversionType, IFormatProvider provider)
at Dapper.SqlMapper.GetValue[T](DbDataReader reader, Type effectiveType, Object val) in /_/Dapper/SqlMapper.cs:line 1399
--- End of inner exception stack trace ---
at Dapper.SqlMapper.ThrowDataException(Exception ex, Int32 index, IDataReader reader, Object value) in /_/Dapper/SqlMapper.cs:line 4001
at Dapper.SqlMapper.QueryRowImpl[T](IDbConnection cnn, Row row, CommandDefinition& command, Type effectiveType) in /_/Dapper/SqlMapper.cs:line 1321
at Dapper.SqlMapper.QuerySingle[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Nullable`1 commandTimeout, Nullable`1 commandType) in /_/Dapper/SqlMapper.cs:line 911
at Program.<Main>$(String[] args) in /Users/rad/Projects/BlogCode/DapperNulls/Program.cs:line 12

This is because NULL cannot be converted to a DateTime.
Which is as expected.
Technically, this code is not correct. If there is a chance that we might not get a result, we should be using QuerySingleOrDefault, rather than QuerySingle.
using (var cn = new SqlConnection("data source=;;uid=sa;pwd=YourStrongPassword123;TrustServerCertificate=true"))
{
var date = cn.QuerySingleOrDefault<DateTime>("SELECT NULL");
Console.WriteLine(date);
}
This still throws the error, but the semantics are clear.
The proper way to address this is to tell Dapper that the result is a nullable DateTime.
The final code is as follows:
using (var cn = new SqlConnection("data source=;;uid=sa;pwd=YourStrongPassword123;TrustServerCertificate=true"))
{
var date = cn.QuerySingle<DateTime?>("SELECT NULL");
if (date.HasValue)
Console.WriteLine(date);
else
Console.WriteLine("A NULL was returned");
}
We have to address the two scenarios - when a NULL returns, or when a valid DateTime returns, achieved by checking the HasValue property.
TLDR
When a NULL is a possible return value, ensure you are using nullable types for value types.
The code is in my GitHub.
Happy hacking!