Non-nullable TypeHandler passed DBNull when selecting scalar results
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 18.4k
- Forks
- 3.7k
- Avg merge
- 5h 8m
- Merged PRs (30d)
- 1
Description
When selecting a single column result for a custom type that is nullable, DBNull is passed to the type handler normally resulting in an InvalidCastException as the type handler is not expecting a null. Since the type handler can't return null either, it has no sensible way to handle the DBNull.
void Main()
{
SqlMapper.AddTypeHandler (new MoneyTypeHandler ());
using (var db = new SqlConnection("Server=(local); Integrated Security=SSPI")) {
db.Open ();
// Normal CLR types work fine when nullable
db.Query<int?> ("SELECT 1").Single ().Dump ();
db.Query<int?> ("SELECT NULL").Single ().Dump ();
// Nullable custom type works correctly when used as a property
db.Query<Foo> ("SELECT 1 AS Cost").Single ().Dump ();
db.Query<Foo> ("SELECT NULL AS Cost").Single ().Dump ();
// Fails when used as a single column scalar result
db.Query<Money?> ("SELECT 1").Single ().Dump ();
db.Query<Money?> ("SELECT NULL").Single ().Dump ();
}
}
public class MoneyTypeHandler : SqlMapper.TypeHandler<Money>
{
public override void SetValue (IDbDataParameter p, Money value)
{
p.DbType = DbType.Int32;
p.Value = value.Value;
}
public override Money Parse (object obj)
{
if (obj is DBNull) {
throw new InvalidCastException ("Expected type int, got type DBNull");
}
return new Money ((int) obj);
}
}
public struct Money
{
private readonly int value;
public Money (int value)
{
this.value = value;
}
public int Value { get { return value; } }
}
public class Foo
{
public Money? Cost { get; set; }
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the supplied C# repro and trace the scalar Query path for nullable custom types and registered type handlers. Confirm the behavior for SELECT NULL and SELECT 1, then verify that a nullable scalar result no longer passes DBNull to a non-nullable handler while ordinary scalar and property mapping cases still work.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, sql
- Domain
- backend-api-design, databases
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100