Dapper.net как создать карту

 public CodeCustomMapper()
  {

    Map(f => f.Name).Column("SName");
    Map(f => f.Name).Column("TName");
    Map(f => f.EmailID).Column("wmail");
    Map(f => f.EmailID).Column("Email");
   }

Я хочу создать такую ​​карту для функции dapper.query.
Кто-нибудь может помочь?
Я хочу сопоставить имена пользовательских столбцов с именами свойств объекта.


public class EntityBase
{
    public string CreatedBy { get; set; }
    public DateTime CreatedOn { get; set; }
}

public class Person :EntityBase
{
    public string SecurityAlias{ get; set; }
    public DateTime Identifier{ get; set; }
}

public class EntityBaseMap
{
    public EntityBaseMap()
    {
        var map = new CustomTypeMap<EntityBase>();
        map.Map("CreatingPerson", "CreatedBy");
        map.Map("CreatedDate", "CreatedOn");
        SqlMapper.SetTypeMap(map.Type, map);
    }
}

public class PersonMap
{
    public PersonMap()
    {
        var map = new CustomTypeMap<Person>();
        map.Map("security_alias", "SecurityAlias");
        map.Map("Id", "Identifier");
        SqlMapper.SetTypeMap(map.Type, map);
    }
}

Когда я называю это:

EntityBaseMap entityBaseMap = new EntityBaseMap();
PersonMap personMap = new PersonMap();

теперь, если я использую сущность Person, она не отображает свойства EntityBase внутри сущности person.


person Gaurav Moolani    schedule 21.12.2012    source источник


Ответы (1)


По сути, вам нужно написать реализацию ITypeMap и IMemberMap, которая внутри может быть основана на любых выбранных вами правилах (соглашения об именах, такие как удаление идентификаторов S и т. д., символов подчеркивания и т. д., атрибутов или пользовательских карт, как в вашем случае).

Вот полный работающий пример, который может помочь:

using Dapper;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Reflection;

class SomeType
{
    public string Bar { get; set; }
    public int Foo { get; set; }
}

static class Program
{
    static Program()
    {
        // only need to do this ONCE
        var oldMap = SqlMapper.GetTypeMap(typeof(SomeType));
        var map = new CustomTypeMap(typeof(SomeType), oldMap);
        map.Map("IFoo", "Foo");
        map.Map("SBar", "Bar");
        SqlMapper.SetTypeMap(map.Type, map);
    }

    static void Main()
    {
        using (var conn = new SqlConnection("Server=.;Database=master;Trusted_Connection=true"))
        {
            conn.Open();

            var row = conn.Query<SomeType>("select 123 as [IFoo], 'abc' as [SBar]").Single();
            Console.WriteLine(row.Foo);
            Console.WriteLine(row.Bar);
        }
    }

    class CustomTypeMap : SqlMapper.ITypeMap
    {
        private readonly Dictionary<string, SqlMapper.IMemberMap> members
            = new Dictionary<string, SqlMapper.IMemberMap>(StringComparer.OrdinalIgnoreCase);
        public Type Type { get { return type; } }
        private readonly Type type;
        private readonly SqlMapper.ITypeMap tail;
        public void Map(string columnName, string memberName)
        {
            members[columnName] = new MemberMap(type.GetMember(memberName).Single(), columnName);
        }
        public CustomTypeMap(Type type, SqlMapper.ITypeMap tail)
        {
            this.type = type;
            this.tail = tail;
        }
        public System.Reflection.ConstructorInfo FindConstructor(string[] names, Type[] types)
        {
            return tail.FindConstructor(names, types);
        }

        public SqlMapper.IMemberMap GetConstructorParameter(
            System.Reflection.ConstructorInfo constructor, string columnName)
        {
            return tail.GetConstructorParameter(constructor, columnName);
        }

        public SqlMapper.IMemberMap GetMember(string columnName)
        {
            SqlMapper.IMemberMap map;
            if (!members.TryGetValue(columnName, out map))
            { // you might want to return null if you prefer not to fallback to the
              // default implementation
                map = tail.GetMember(columnName);
            }
            return map;
        }
    }
    class MemberMap : SqlMapper.IMemberMap
    {
        private readonly MemberInfo member;
        private readonly string columnName;
        public MemberMap(MemberInfo member, string columnName)
        {
            this.member = member;
            this.columnName = columnName;
        }
        public string ColumnName { get { return columnName; } }
        public System.Reflection.FieldInfo Field { get { return member as FieldInfo; } }
        public Type MemberType { get {
            switch (member.MemberType)
            {
                case MemberTypes.Field: return ((FieldInfo)member).FieldType;
                case MemberTypes.Property: return ((PropertyInfo)member).PropertyType;
                default: throw new NotSupportedException();
            }
        } }
        public System.Reflection.ParameterInfo Parameter { get { return null; } }
        public System.Reflection.PropertyInfo Property { get { return member as PropertyInfo; } }
    }
}
person Marc Gravell    schedule 21.12.2012
comment
Спасибо, Марк, за быстрый ответ. Еще один вопрос, если я использую приложение MVC, в котором у меня есть уровень данных (где я буду использовать dapper). Мой вопрос: где я могу написать код, предоставленный вами, чтобы мне приходилось делать это сопоставление при запуске только один раз? - person Gaurav Moolani; 22.12.2012
comment
@CodeCrusher Проще всего было бы вызвать метод Init в DAL из global.asax, рядом с тем, где вы настраиваете маршруты MVC. - person Marc Gravell; 22.12.2012
comment
Привет, Марк, код не работает, если у меня есть базовая сущность. это не отображение свойств базовой сущности. хотя я сопоставляю базовый объект отдельно. - person Gaurav Moolani; 02.01.2013
comment
@CodeCrusher, можете ли вы привести пример? - person Marc Gravell; 02.01.2013
comment
Клиент открытого класса: EntityBase. Entitybase я отображаю, как указано u . также Клиент отдельно. - person Gaurav Moolani; 02.01.2013
comment
Привет, Марк, я отредактировал свой пост и добавил пример, пожалуйста, смотрите пример выше в сообщении. - person Gaurav Moolani; 02.01.2013
comment
я думаю, что dapper также должен автоматически проверять свои базовые классы - person Gaurav Moolani; 03.01.2013
comment
@CodeCrusher, разве это не все специфично для CustomTypeMap? ты не можешь просто изменить CustomTypeMap? - person Marc Gravell; 03.01.2013
comment
Я могу изменить CustomTypeMap, но если такое условие присутствует. Дочерний класс: - без карт и базового класса с картами, тогда я должен принудительно сопоставить дочерний класс, даже если у него нет карт. - person Gaurav Moolani; 03.01.2013
comment
Спасибо за ваши усилия, я нахожусь в такой сложной ситуации. Если у меня есть 100 объектов, все они унаследованы от базового класса (который требует пользовательского сопоставления). и только 10 из них нуждаются в сопоставлении, тогда мне нужно применить CustomTypeMap ко всем 100 объектам. - person Gaurav Moolani; 03.01.2013
comment
любое решение? для проблемы - person Gaurav Moolani; 04.01.2013
comment
Нет ли более простого решения этой распространенной проблемы необходимости сопоставления имени столбца SQL с полем POCO? Я бы предпочел не прибегать к атрибутам. Почему что-то подобное не включено в Dapper по умолчанию? - person crush; 13.10.2014
comment
@crush, потому что весь смысл dapper состоит в том, чтобы решить проблему 98%, не вводя огромные объемы сложности, просто для поддержки 2% - person Marc Gravell; 13.10.2014
comment
@MarcGravell Возможность легко сопоставить имя столбца с полем, не прибегая к украшению полей атрибутом (который эффективно связывает схему базы данных с POCO), кажется чем-то, что ближе к решению 98%, чем 2%. Вышеупомянутое решает очень широкую проблему, не связанную с реализацией. Я понимаю, о чем вы говорите, но я чувствую, что CustomTypeMapper является важной частью набора инструментов Dapper. В итоге я добавил это в каждый проект, который я пишу, который использует Dapper, поскольку я отказываюсь связывать POCO с реализацией базы данных. Просто мои 2 цента. - person crush; 13.10.2014
comment
Возможно, лучший ответ можно найти на stackoverflow.com/a/12615036/521554, где добавляются атрибуты в POCO. class, как это делается в EF. - person LosManos; 11.04.2015