Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Non-nullable TypeHandler passed DBNull when selecting scalar results #224

Copy link
Copy link

Description

@chilversc
Issue body actions

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; }
}
Reactions are currently unavailable

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.