我是Dapper微型ORM的新手。到目前为止,我能够将它用于简单的ORM相关的东西,但我不能将数据库列名与类属性映射。

例如,我有如下的数据库表:

Table Name: Person
person_id  int
first_name varchar(50)
last_name  varchar(50)

我有一个叫Person的类:

public class Person 
{
    public int PersonId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

请注意,表中的列名与我试图将从查询结果中获得的数据映射到的类的属性名不同。

var sql = @"select top 1 PersonId,FirstName,LastName from Person";
using (var conn = ConnectionFactory.GetConnection())
{
    var person = conn.Query<Person>(sql).ToList();
    return person;
}

上面的代码将无法工作,因为列名不匹配对象的(Person)属性。在这种情况下,有什么我可以在Dapper手动映射(例如person_id => PersonId)与对象属性的列名?


当前回答

如果您使用的是。net 4.5.1或更高版本的结帐Dapper。FluentColumnMapping用于映射LINQ样式。它可以让你完全将db映射与你的模型分开(不需要注释)

其他回答

我知道这是一个相对较老的线程,但我想我会把我所做的放在那里。

我希望属性映射能够全局工作。您可以匹配属性名(即默认值),也可以匹配类属性上的列属性。我也不想为我映射到的每个类都设置这个。因此,我创建了一个DapperStart类,我在应用程序启动时调用:

public static class DapperStart
{
    public static void Bootstrap()
    {
        Dapper.SqlMapper.TypeMapProvider = type =>
        {
            return new CustomPropertyTypeMap(typeof(CreateChatRequestResponse),
                (t, columnName) => t.GetProperties().FirstOrDefault(prop =>
                    {
                        return prop.Name == columnName || prop.GetCustomAttributes(false).OfType<ColumnAttribute>()
                                   .Any(attr => attr.Name == columnName);
                    }
                ));
        };
    }
}

很简单。我不知道在写这篇文章的时候会遇到什么问题,但它是有效的。

在打开到数据库的连接之前,为每个poco类执行这段代码:

// Section
SqlMapper.SetTypeMap(typeof(Section), new CustomPropertyTypeMap(
    typeof(Section), (type, columnName) => type.GetProperties().FirstOrDefault(prop =>
    prop.GetCustomAttributes(false).OfType<ColumnAttribute>().Any(attr => attr.Name == columnName))));

然后像这样将数据注释添加到poco类中:

public class Section
{
    [Column("db_column_name1")] // Side note: if you create aliases, then they would match this.
    public int Id { get; set; }
    [Column("db_column_name2")]
    public string Title { get; set; }
}

之后,你就万事俱备了。只需要进行查询调用,就像这样:

using (var sqlConnection = new SqlConnection("your_connection_string"))
{
    var sqlStatement = "SELECT " +
                "db_column_name1, " +
                "db_column_name2 " +
                "FROM your_table";

    return sqlConnection.Query<Section>(sqlStatement).AsList();
}

搞砸映射是进入真正ORM领域的边缘。与其与之斗争,让Dapper保持真正简单(快速)的形式,不如像这样稍微修改SQL:

var sql = @"select top 1 person_id as PersonId,FirstName,LastName from Person";

在一段时间内,以下方法应该有效:

Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;

凯莱布·佩德森的解决方案对我很有效。我更新了ColumnAttributeTypeMapper以允许自定义属性(在同一个域对象上需要两个不同的映射),并更新了属性以允许在需要派生字段且类型不同的情况下使用私有setter。

public class ColumnAttributeTypeMapper<T,A> : FallbackTypeMapper where A : ColumnAttribute
{
    public ColumnAttributeTypeMapper()
        : base(new SqlMapper.ITypeMap[]
            {
                new CustomPropertyTypeMap(
                   typeof(T),
                   (type, columnName) =>
                       type.GetProperties( BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault(prop =>
                           prop.GetCustomAttributes(true)
                               .OfType<A>()
                               .Any(attr => attr.Name == columnName)
                           )
                   ),
                new DefaultTypeMap(typeof(T))
            })
    {
        //
    }
}