<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Shafqat Ahmed</title>
    <description>The latest articles on DEV Community by Shafqat Ahmed (@shafqat_ahmed_04d479f9a03).</description>
    <link>https://dev.to/shafqat_ahmed_04d479f9a03</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3133252%2F75d91f86-3a5b-426b-be5d-7042e7bf4256.jpg</url>
      <title>DEV Community: Shafqat Ahmed</title>
      <link>https://dev.to/shafqat_ahmed_04d479f9a03</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/shafqat_ahmed_04d479f9a03"/>
    <language>en</language>
    <item>
      <title>Smarter Generic Mapping in Dapper.FluentMap while using DataAnnotations</title>
      <dc:creator>Shafqat Ahmed</dc:creator>
      <pubDate>Tue, 29 Jul 2025 21:50:40 +0000</pubDate>
      <link>https://dev.to/shafqat_ahmed_04d479f9a03/smarter-automapping-in-dapperfluentmap-while-dataannotations-attributes-3il9</link>
      <guid>https://dev.to/shafqat_ahmed_04d479f9a03/smarter-automapping-in-dapperfluentmap-while-dataannotations-attributes-3il9</guid>
      <description>&lt;p&gt;I am using postgres sql as database. I have mapped my classes earlier   using Entity Framework and used the Column[("name")] attribute. Now that I have switched to Dapper, it seemed Dapper does not read any of the column attributes that I have used in my DTO/POCO classes. Ah! That's going to be a problem.&lt;/p&gt;

&lt;p&gt;So my class kinda looks like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class Role
{
    [Column("role_id")]
    public long RoleID { get; set; }

    [Column("role_name")]
    public string RoleName { get; set; }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this is going to be an issue. I could rewrite my queries like this ---&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const string sql =
    @"SELECT role_id      AS RoleID,
             role_name    AS RoleName
        FROM public.role
       WHERE role_id = @id;";
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this is a hassle that I dont want to deal with. It seems Dapper.FluentMap has a way to map these column names to properties but that does not happen thorough attributes. Here is how to do that ---&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class RoleMap : EntityMap&amp;lt;Role&amp;gt;
{
    public RoleMap()
    {
        Map(r =&amp;gt; r.RoleID).ToColumn("role_id");
        Map(r =&amp;gt; r.RoleName).ToColumn("role_name");
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then register the mapping class like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FluentMapper.Initialize(c =&amp;gt; c.AddMap(new RoleMap()));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now I ain't going to write one class for each entities that I have created. So I created a generic class called the ColumnMapper and that takes care of the mapping if your DTO/POCO class uses System.ComponentModel.DataAnnotations.Schema and maps using the ColumnAttribute. Which I already do. So here is the class that does that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class ColumnMapper &amp;lt; T &amp;gt;: EntityMap &amp;lt; T &amp;gt; where T: class {
    public ColumnMapper() {
      // Get all public instance properties of the entity type T.
      PropertyInfo[] infos = typeof (T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

      foreach(var propertyInfo in infos) {
        // Check if the property has a [Column] attribute.
        var columnAttr = propertyInfo.GetCustomAttribute &amp;lt; System.ComponentModel.DataAnnotations.Schema.ColumnAttribute &amp;gt; ();

        if (columnAttr != null) {
          // --- Reflection to call Map(lambda).ToColumn(columnName) ---


          var parameter = Expression.Parameter(typeof (T), "x");
          var property = Expression.Property(parameter, propertyInfo);

          var convert = Expression.Convert(property, typeof (object));
          var lambda = Expression.Lambda &amp;lt; Func &amp;lt; T,
            object &amp;gt;&amp;gt; (convert, parameter);

           var mapMethod = typeof (EntityMap &amp;lt; T &amp;gt; )
            .GetMethod("Map", BindingFlags.Instance | BindingFlags.NonPublic);

          if (mapMethod == null) {

            throw new InvalidOperationException("Could not find the 'Map' method via reflection. The Dapper.FluentMap API may have changed.");
          }

          var propertyMap = mapMethod.Invoke(this, new object[] {
            lambda
          });

          var toColumnMethod = propertyMap.GetType()
            .GetMethod("ToColumn", new [] {
              typeof (string), typeof (bool)
            });

          if (toColumnMethod != null) {
            toColumnMethod.Invoke(propertyMap, new object[] {
              columnAttr.Name, false
            });
          }
        }
      }
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then I can call this generic mapper class like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; FluentMapper.Initialize(cfg =&amp;gt;
        {
            cfg.AddMap(new ColumnMapper&amp;lt;User&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;Role&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;Permission&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;RolePermissionMap&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;RoleUserMap&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;ServiceInfo&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;ServiceInstance&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;Queue&amp;gt;());
            cfg.AddMap(new ColumnMapper&amp;lt;Token&amp;gt;());
        });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Walla! I am done!&lt;/p&gt;

&lt;p&gt;Since this is called only once during startup it has no performance issues either. Let me know what you guys think.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
