2013-02-11 4 views
13

мне удалось получить что-то и работает сегодня, как небольшой проект песочница/POC, но, казалось, поднять мою голову на одном вопросе ...Dapper. Карта SQL Column с пробелами в именах столбцов

Вопрос:

Есть ли способ получить dapper для сопоставления имен столбцов SQL с пробелами в них.

У меня есть что-то в этом роде, так как мой результирующий набор.

Например:

SELECT 001 AS [Col 1], 
     901 AS [Col 2], 
     00454345345345435349 AS [Col 3], 
     03453453453454353458 AS [Col 4] 
FROM [Some Schema].[Some Table] 

И мой класс будет выглядеть следующим образом

public class ClassA 
    {   
     public string Col1 { get; set; }  

     public string Col2 { get; set; } 

     ///... etc 
    } 

Моя реализация выглядит, как это в настоящее время

public Tuple<IList<TClass>, IList<TClass2>> QueryMultiple<TClass, TClass2>(object parameters) 
{ 
     List<TClass> output1; 
     List<TClass2> output2; 

     using (var data = this.Connection.QueryMultiple(this.GlobalParameter.RpcProcedureName, parameters, CommandType.StoredProcedure)) 
     { 
      output1 = data.Read<TClass>().ToList(); 
      output2 = data.Read<TClass2>().ToList(); 
     } 

     var result = new Tuple<IList<TClass>, IList<TClass2>>(output1, output2); 
     return result; 
    } 

Примечание: SQL, не могут быть изменены каким-либо образом.

В настоящее время я просматриваю код dapper, и моим единственным предсказуемым решением является добавление некоторого кода, чтобы «уговорить» сравнение столбцов, но пока не так много удачи.

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

+0

У меня есть такая же потребность. Я обошел его, добавив псевдонимы ко всем столбцам в моем запросе, но это невероятно утомительно. Нижеприведенные решения могут работать, но было бы неплохо, если бы Dapper мог просто добавить свойство/параметр, чтобы игнорировать пробелы, а не всем, кто должен был добавить клиентов.Это юридические имена, и они должны иметь возможность сопоставлять их с небольшими усилиями. –

ответ

8

Один из вариантов здесь - перейти через динамический/не общий API, а затем извлечь значения через API IDictionary<string,object> для каждой строки, но это может быть немного утомительно.

В качестве альтернативы вы можете создать собственный картограф и рассказать о нем; например:

SqlMapper.SetTypeMap(typeof(ClassA), new RemoveSpacesMap()); 

с:

class RemoveSpacesMap : Dapper.SqlMapper.ITypeMap 
{ 

    System.Reflection.ConstructorInfo SqlMapper.ITypeMap.FindConstructor(string[] names, Type[] types) 
    { 
     return null; 
    } 

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

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetMember(string columnName) 
    { 
     var prop = typeof(ClassA).GetProperty(columnName.Replace(" ", "")); 
     return prop == null ? null : new PropertyMemberMap(columnName, prop); 
    } 
    class PropertyMemberMap : Dapper.SqlMapper.IMemberMap 
    { 
     private string columnName; 
     private PropertyInfo property; 
     public PropertyMemberMap(string columnName, PropertyInfo property) 
     { 
      this.columnName = columnName; 
      this.property = property; 
     } 
     string SqlMapper.IMemberMap.ColumnName 
     { 
      get { throw new NotImplementedException(); } 
     } 

     System.Reflection.FieldInfo SqlMapper.IMemberMap.Field 
     { 
      get { return null; } 
     } 

     Type SqlMapper.IMemberMap.MemberType 
     { 
      get { return property.PropertyType; } 
     } 

     System.Reflection.ParameterInfo SqlMapper.IMemberMap.Parameter 
     { 
      get { return null; } 
     } 

     System.Reflection.PropertyInfo SqlMapper.IMemberMap.Property 
     { 
      get { return property; } 
     } 
    } 
} 
+1

Спасибо! На данный момент мне пришлось удалить dapper, поскольку это было необходимо для небольшого (бросившегося) доказательства концепции. Но мне нравится структура/библиотека, я определенно думаю, что буду добавлять ее обратно. –

+0

@transistor вы можете показать пример этой ошибки? –

+0

А .. смотря на это, я полагаю, мне нужно было бы реализовать метод FindConstructor в 'RemoveSpacesMap', правильно? К сожалению! Сожалею. – transistor1

4

У меня была аналогичная проблема при попытке получить сопоставляются результаты вызова системной процедуры sp_spaceused. Код Marc не совсем сработал для меня, поскольку он жаловался на то, что не смог найти конструктор по умолчанию. Я также сделал свою версию обобщенной, чтобы ее теоретически можно было повторно использовать. Это может быть не самый быстрый исполняемый фрагмент кода, но он работает для меня, и в нашей ситуации эти вызовы происходят нечасто.

class TitleCaseMap<T> : SqlMapper.ITypeMap where T: new() 
{ 
    ConstructorInfo SqlMapper.ITypeMap.FindConstructor(string[] names, Type[] types) 
    { 
     return typeof(T).GetConstructor(Type.EmptyTypes); 
    } 

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetConstructorParameter(ConstructorInfo constructor, string columnName) 
    { 
     return null; 
    } 

    SqlMapper.IMemberMap SqlMapper.ITypeMap.GetMember(string columnName) 
    { 
     string reformattedColumnName = string.Empty; 

     foreach (string word in columnName.Replace("_", " ").Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)) 
     { 
      reformattedColumnName += char.ToUpper(word[0]) + word.Substring(1).ToLower(); 
     } 

     var prop = typeof(T).GetProperty(reformattedColumnName); 

     return prop == null ? null : new PropertyMemberMap(prop); 
    } 

    class PropertyMemberMap : SqlMapper.IMemberMap 
    { 
     private readonly PropertyInfo _property; 

     public PropertyMemberMap(PropertyInfo property) 
     { 
      _property = property; 
     } 
     string SqlMapper.IMemberMap.ColumnName 
     { 
      get { throw new NotImplementedException(); } 
     } 

     FieldInfo SqlMapper.IMemberMap.Field 
     { 
      get { return null; } 
     } 

     Type SqlMapper.IMemberMap.MemberType 
     { 
      get { return _property.PropertyType; } 
     } 

     ParameterInfo SqlMapper.IMemberMap.Parameter 
     { 
      get { return null; } 
     } 

     PropertyInfo SqlMapper.IMemberMap.Property 
     { 
      get { return _property; } 
     } 
    } 
} 
4

Там в NuGet пакет Dapper.FluentMap, что позволяет добавить имя столбца отображения (включая пробелы). Это похоже на EntityFramework.

// Entity class. 
public class Customer 
{ 
    public string Name { get; set; } 
} 

// Mapper class. 
public class CustomerMapper : EntityMap<Customer> 
{ 
    public CustomerMapper() 
    { 
     Map(p => p.Name).ToColumn("Customer Name"); 
    } 
} 

// Initialise like so - 
FluentMapper.Initialize(a => a.AddMap(new CustomerMapper())); 

см. https://github.com/henkmollema/Dapper-FluentMap для больше.

+0

Красивый пример. Очень проста в использовании, и это пакет NuGet – joetinger

+0

@David, я инициализировал FluentMapper. Но, похоже, это не работает. Наверное, я что-то упускаю. Не могли бы вы рассказать о том, как я могу заставить его работать, если мой текущий код - «return connection.Query (« SELECT «My Name» [Customer Name] »). First();' Как это можно сделать для работы вернуть объект Customer? – user007

+0

@ user007 Вы можете показать мне свой класс клиентов? И где вы делаете картографирование? –

 Смежные вопросы

  • Нет связанных вопросов^_^