5

I have a table structure like this:

Table tbUser

--ID (int)

--Name (varchar)

--Birthday (datetime)

--Rating (double)

When

"SELECT * FROM tbUser"

I want each row in query result looks like (turns every column into string format):

row["ID"] = "1";
row["Name"] "John"
row["Birthday"] = "1980-01-01"
row["rating"] = "3.4"

The reason I need strings as result is they are easy to manipulate/format/display and some times safer (If another engineer changed column type in DB --e.g. "rating" column changed from double to int, the program is less likely throw exception as it only cares about strings)

I know there's a way to convert a DapperRow to IDictionary<string, object>, which is very close to IDictionary<string, string>;

var result = conn.Query("SELECT * FROM tbUser");
foreach (IDictionary<string, object> row in result) {
  // I have to write my own object->string conversion in every loop
}

Any suggestion is highly appreciated!

Community
  • 1
  • 1
ineztia
  • 815
  • 1
  • 13
  • 29
  • Could you not just create your own class and parse the returning result. Having full control of what gets returned? – Hexie May 03 '16 at 03:07
  • 3
    `If another engineer changed column type in DB --e.g. "rating" column changed from double to int, the program is less likely throw exception as it only cares about strings` Just so you know - this is terrible thinking. This will only *hide* the problem and make it impossible to debug. You *want* to fail hard and fail fast. You don't want to treat a value as something is-kind-of-is-but-isn't. If an engineer changed the type of a column, it would imply the original code was *wrong*, and thus should be updated with the type change as well. – Rob May 03 '16 at 03:29

2 Answers2

13

No, Dapper doesn't do it for you (nor should it!). First of all - would the conversion be done in the database, or in code? And how are things formatted? (How do we format 2,000.20? Not all cultures use . as a decimal place, nor , as thousands separators. Gets even worse for dates).

Nevertheless, you can write something like this:

var data = Connection.Query("SELECT TOP 100 * FROM People") 
                      as IEnumerable<IDictionary<string, object>>;

var outData = data.Select(r => r.ToDictionary(d => d.Key, d => d.Value?.ToString()));

Or you can write your own extension:

public static class DapperExtensions
{
    public static IEnumerable<IDictionary<string, string>> QueryDictionary(this IDbConnection connection, string query)
    {
        var data = Dapper.SqlMapper.Query(connection, query) as IEnumerable<IDictionary<string, object>>;
        return data.Select(r => r.ToDictionary(d => d.Key, d => d.Value?.ToString()));
    }
}

And use it as so:

var data = Connection.QueryDictionary("SELECT TOP 100 * FROM People");
Rob
  • 26,989
  • 16
  • 82
  • 98
1

This seems to have already been answered.

You would need to create a model / class, then follow this code snippet to achieve what you are wanting;

Dictionary<string, SP> dictionary = connection.Query<SP>(@"
SELECT 
     routine_name AS RoutineName,
     created AS Created,
     modified AS Modified
FROM PROCEDURES
").ToDictionary(m => m.RoutineName, m => m);

See this thread for the full answer - How to put objects into a dictionary using Dapper in C#?

Community
  • 1
  • 1
Hexie
  • 3,955
  • 6
  • 32
  • 55
  • This is a completely different question. Nevertheless, if the solution were exactly as written in the linked answer, you should vote to close as a duplicate, not post the same answer here – Rob May 03 '16 at 03:27
  • 1
    It was to be used and an example of creating his own model / class to use - not being the exact answer. Should help point in the right direction no? – Hexie May 03 '16 at 03:30
  • 1
    Yes, I understand that - I'm not having a go at you, just giving you a tip for next time. If the question were solved by the above, it would be a direct duplicate (even though the models are not the same). Typically duplicate answers are actually harmful, as it messes with the SEO and rankings of search results. – Rob May 03 '16 at 03:32
  • @Rob Ah, that makes sense. :) Thanks for the advise. – Hexie May 03 '16 at 03:56