DapperLib / DapperLib/Dapper

Custom TypeHandler Parse method only being passed the first column of result from QueryAsync

Open
#929 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
C#
Stars
18.4k
Forks
3.7k
Avg merge
5h 8m
Merged PRs (30d)
1

Description

Imagine this schema

public class Item {
    public string Id;
    public string Content;
    public string Name;
    public string[] Keywords;
}

The Id and keywords are stored as a bigint and nvarchar in the db so I need to transform them using some business logic to get them into form I want for the user. Dapper can natively handle the long to string without throwing an excepting and then I can get the form that I want with some further conversion/casting. But the keywords require a custom mapper because it's a character delimited string that does not directly map to an array. Below is the SqlMapper class with the business logic removed.

public class ItemJsonSchemaHandler : SqlMapper.TypeHandler<ItemJsonSchema> 
        
    public override void SetValue(IDbDataParameter parameter, Item value)
    {
        throw new System.NotImplementedException();
    }

    public override ItemJsonSchema Parse(object value)
    {
        if (value is DialtoneTemplateJsonSchema)
        {
           // transform logic
        }
        return null;
    }
}

The following line of code queries the db.

await this.sqlAccess.QueryAsync<ItemJsonSchema>(ItemSqlQueries.GetQuery, new { ItemId = itemId })

Where ItemSqlQueries.GetQuery is

SELECT * FROM [dbo].[Item] item
WHERE item.Id = @ItemId

When the query is made the Parse method is called, but the value parameter only contains the value of the Id. It does not contain the rest of the values contained in the row. I know the entire row is read because if I instead query the database as

await this.sqlAccess.QueryAsync<object>(ItemSqlQueries.GetQuery, new { ItemId = itemId })

The object returned is of the type DapperRow and it contains all the expected values. Is this expected behavior and I'm misunderstanding the purpose of the TypeHandler? If so does Dapper natively allow me to handle this case? Or do I need to get it as an object and access the properties?

Apologies if I'm misunderstanding how the type handlers are used and this isn't any sort of a real issue, but I can find next to nothing anything about how the Parse class works for any remotely complex complexes. Based on the examples in the repo, I'd fully expect the entire row.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the custom TypeHandler.Parse implementation and the QueryAsync call shown in the issue; compare them with QueryAsync, which returns a DapperRow containing all columns. Determine whether Parse is intended to receive one column or a complete row, then verify the expected behavior against Dapper's TypeHandler examples or tests. Done means the supported mapping behavior and an appropriate handling path are clear.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp, sql
Domain
backend, database
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.