Skip to content

Instantly share code, notes, and snippets.

@kalebpederson
Last active July 20, 2025 23:04
Show Gist options
  • Select an option

  • Save kalebpederson/5460509 to your computer and use it in GitHub Desktop.

Select an option

Save kalebpederson/5460509 to your computer and use it in GitHub Desktop.
namespace YourNamespace
{
/// <summary>
/// Uses the Name value of the <see cref="ColumnAttribute"/> specified to determine
/// the association between the name of the column in the query results and the member to
/// which it will be extracted. If no column mapping is present all members are mapped as
/// usual.
/// </summary>
/// <typeparam name="T">The type of the object that this association between the mapper applies to.</typeparam>
public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
{
public ColumnAttributeTypeMapper()
: base(new SqlMapper.ITypeMap[]
{
new CustomPropertyTypeMap(
typeof(T),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName)
)
),
new DefaultTypeMap(typeof(T))
})
{
}
}
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ColumnAttribute : Attribute
{
public string Name { get; set; }
}
public class FallbackTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
foreach (var mapper in _mappers)
{
try
{
ConstructorInfo result = mapper.FindConstructor(names, types);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetConstructorParameter(constructor, columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public ConstructorInfo FindExplicitConstructor()
{
return _mappers
.Select(mapper => mapper.FindExplicitConstructor())
.FirstOrDefault(result => result != null);
}
}
}
@Anda001
Copy link
Copy Markdown

Anda001 commented Jul 7, 2022

I can use it to 'query',but can't use to 'update' or 'insert'.

@RamseJones
Copy link
Copy Markdown

I followed everything here, created all classes of ColumnAttributeTypeMapper.
Add on Startup =>
services.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
TypeMapper.Initialize("Dapper.Core.Entities");
My Class
public class Product
{
[Column("Id_Prod")]
public int Id { get; set; }
}
Repository
public async Task<IReadOnlyList> GetAllAsync()
{
var sql = "SELECT * FROM Products";
using (var connection = new SqlConnection(configuration.GetConnectionString("DefaultConnection")))
{
connection.Open();
var result = await connection.QueryAsync(sql);
return result.ToList();
}
}
Dapper 1.50 and AutoMapper 8.0
I feel it's missing one little detail, but i'm searching for days.

@AlaskanDruid
Copy link
Copy Markdown

Anyone get this working with Dapper 2.1.66 yet?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment