-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
Open
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; }
}