Вручную сопоставьте имена столбцов со свойствами класса - PullRequest
151 голосов
/ 18 января 2012

Я новичок в Dapper micro 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) имена столбцов со свойствами объекта?

Ответы [ 15 ]

3 голосов
/ 03 июня 2016

Если вы используете .NET 4.5.1 или выше, извлекайте Dapper.FluentColumnMapping для отображения стиля LINQ.Это позволяет полностью отделить отображение БД от вашей модели (нет необходимости в аннотациях)

1 голос
/ 24 апреля 2015

Решение Калеба Педерсона сработало для меня. Я обновил ColumnAttributeTypeMapper, чтобы разрешить настраиваемый атрибут (требовалось два разных сопоставления для одного и того же объекта домена), и обновил свойства, чтобы разрешить частные установщики в тех случаях, когда необходимо получить поле и типы различаются.

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))
            })
    {
        //
    }
}
1 голос
/ 25 апреля 2013

для всех вас, кто использует Dapper 1.12. Вот что вам нужно сделать, чтобы это сделать:

Добавить новый класс атрибута столбца:
  [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property]

  public class ColumnAttribute : Attribute
  {

    public string Name { get; set; }

    public ColumnAttribute(string name)
    {
      this.Name = name;
    }
  }

Найдите эту строку:
map = new DefaultTypeMap(type);

и закомментируйте ее.

Напишите вместо этого:
        map = new CustomPropertyTypeMap(type, (t, columnName) =>
        {
          PropertyInfo pi = t.GetProperties().FirstOrDefault(prop =>
                            prop.GetCustomAttributes(false)
                                .OfType<ColumnAttribute>()
                                .Any(attr => attr.Name == columnName));

          return pi != null ? pi : t.GetProperties().FirstOrDefault(prop => prop.Name == columnName);
        });

0 голосов
/ 05 апреля 2019

Простое решение проблемы, которую пытается решить Kaleb, - просто принять имя свойства, если атрибут столбца не существует:

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

0 голосов
/ 19 октября 2018

Я знаю, что это относительно старая тема, но я решил добавить туда то, что я сделал.

Я хотел, чтобы отображение атрибутов работало глобально.Либо вы соответствуете имени свойства (по умолчанию), либо вы соответствуете атрибуту столбца в свойстве класса.Я также не хотел устанавливать это для каждого класса, который я отображал.Поэтому я создал класс 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);
                    }
                ));
        };
    }
}

Довольно просто.Не знаю, с какими проблемами я столкнусь, поскольку я только что написал это, но это работает.

...