Search code examples
c#dapper-extensions

Map SQL to class in Dapper


My problem: When using this extension it only maps up the ID value from the database to class object.

So I'm curious how do i make it map the other values?

C# Mapper

 public class SoftwareReleaseTypeHandle : SqlMapper.TypeHandler<SoftwareRelease>
    {
        public override SoftwareRelease Parse(object value)
        {
            if (value == null || value is DBNull)
            {
                return null;
            }

            SoftwareRelease rel = new SoftwareRelease();
            rel.ID = (Guid)value;

            return rel;
        }

        public override void SetValue(IDbDataParameter parameter, SoftwareRelease value)
        {
            parameter.DbType = DbType.Guid;
            parameter.Value = value.ID.ToString();
        }
    }

The SQL table looks like this:

CREATE TABLE [dbo].[SoftwareRelease](
    [ID] [uniqueidentifier] NOT NULL,
    [Type] [tinyint] NOT NULL,
    [ReleaseType] [tinyint] NOT NULL,
    [Version] [nchar](30) NOT NULL,
    [ZipFile] [varbinary](max) NOT NULL,
    [Date] [datetime] NOT NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

The reason i used this mapper was so in other places in my code i could do, and it would automaticly get mapped up:

class MyInstallation
{
 public string Bla;
 public string BlaBla;
 SoftwareRelease MyInstallation;
}

And when i then use Dapper to get from a table that looks like.

CREATE TABLE [dbo].[MyInstallation](
        [ID] [uniqueidentifier] NOT NULL,
        [Bl] [nchar](30) NOT NULL,
        [BlaBla] [nchar](30) NOT NULL,
        [MyInstallation] [uniqueidentifier] NOT NULL,
    ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Solution

  • Dapper type handlers are intended to map a single column value in your database to a single member in your POCO. They are used for types that Dapper's core doesn't understand - generally anything that isn't a .NET core type.

    You don't say exactly what you need to do but if you're just trying to read SoftwareRelease rows from the database then you can simply do the following:

    myDb.Query<SoftwareRelease>("SELECT * FROM SoftwareRelease");
    

    Update

    Sounds like what you really want is multi-mapping. If you have the following query:

    SELECT a.Bla, a.BlaBla, b.*
    FROM MyInstallation a
    INNER JOIN SoftwareRelease b ON a.SoftwareReleaseId = b.ID
    

    Then you can use the following to populate the object:

    myDB.Query<MyInstallation, SoftwareRelease, MyInstallation>(
        sql, 
        (installation, softwareRelease) => {
            installation.SoftwareRelease = softwareRelease;
        });