2016-01-12 1 views
0

Я пытаюсь получить ExpressMapper для отображения из DataReader в объект (в основном, Sqlite Rows -> Objects). У меня был успех с AutoMapper, но я нашел некоторые другие проблемы, которые заставили меня искать другой инструмент карты.C# Использование mapper для сопоставления DataReader с объектом

В AutoMapper я использовал следующий код, но в ExpressMapper все строковые свойства NULL, а long prop всегда 0, это означает, что отображение не работает. Попробовал посмотреть некоторые примеры для ExpressMapper, но не нашел. Вы можете помочь? Кроме того, есть ли другие карты помимо AutoMapper (и, возможно, ExpressMapper), которые могут помочь мне достичь этого сценария?

Спасибо!

public class ImportedFiles 
{ 
    public Int64 Id { get; set; } 
    public String FileName { get; set; } 
    public String Hash { get; set; } 

    public ImportedFiles() 
    { 

    } 

} 

private static void ReadImportedFiles() 
    { 
     var lst = ReadData<ImportedFiles>("SELECT * FROM ImportedFiles").ToList(); 
    } 

public static IEnumerable<T> ReadData<T>(string queryString) 
     { 
      using (var connection = new SQLiteConnection(ConnectionBuilder.ConnectionString)) 
      { 
       connection.Open(); 
       using (var cmd = connection.CreateCommand()) 
       { 
        cmd.CommandText = queryString; 
        using (var reader = cmd.ExecuteReader()) 
         if (reader.HasRows) 
          while (reader.Read()) 
           yield return Mapper.Map<IDataRecord, T>(reader); 
       } 
      } 
     } 
+0

В чем вопрос? Вам нужна помощь с Automapper или ExpressMapper? Как только вы определите, с какой из них вам потребуется помощь, пожалуйста, покажите пример кода (и, вероятно, некоторые примеры данных), который воспроизводит проблему, в которой вам нужна помощь. – PatrickSteele

+0

Что касается Expressmapper: К сожалению, Expressmapper пока не поддерживает отображение DataReader в Object. Основная проблема, что каждый раз IDataRecord мог иметь разные имена столбцов на DataReader, которые заставляют Expressmapper компилировать сопоставления для каждого DataReader без кеша, но я думаю, что все равно двойное выполнение кэширования, поэтому я только что зарегистрировал проблему: https://github.com/expressmapper/ExpressMapper/issues/74 в Github, который, вероятно, будет включен в версию 2.0. –

ответ

0

есть какие-либо другие картографы, кроме AutoMapper (и, возможно, ExpressMapper), который может помочь мне достичь этого сценария?

Да. Как правило, они называются Объектно-реляционные Mappers (сокращены до O/RM или просто ORM). Здесь очень много; несколько самых популярных для платформы .NET: Entity Framework и NHibernate.

Я думаю, вы используете неправильный класс инструмента (объектно-ориентированные объекты) для задачи (object-relational mapping).

Матрицы объектов для объекта предназначены для сопоставления между тесно связанными, строго типизированными, содержащими данные классами, как правило, для сохранения кода преобразования вручную. Они не предназначены для сопоставления с или более общих контейнеров данных, таких как DataRow, или для решения других проблем, связанных с подключением к сети, которые приходят в игру при работе с реляционной базой данных.

0

ExpressMapper способен отображать данные DataRow. Это должно решить вашу проблему.

Просто реорганизовать свой код для работы с DataRow. И предварительно зарегистрируйте отображение.

Так что, если вы пишете:

yield return Mapper.Map<DataRow, T>(row); 

И делать отображения (один раз для каждого приложения), как я предложил:

 Mapper.Register<DataRow, ImportedFiles>() 
      .Member(dest => dest.Id, 
        src => DBNull.Value == src["Id"] ? 0 : (double)src["Id"]) 
      .Member(dest => dest.FileName, 
        src => DBNull.Value == src["FileName"] ? String.Empty : (string)src["FileName"]) 
      .Member(dest => dest.Hash, 
        src => DBNull.Value == src["Hash"] ? String.Empty : (string)src["Hash"]) 
      ; 

Вы можете использовать его.


[Изменено]

В случае, если вам нужно отобразить более одного источника (т.е. более чем один DataTable), то вы можете написать DataRowAdapter, который будет отличать ваше отображение и знать ExpressMapper (или что-то ORM, который вы хотите использовать - это применимо ко всем ORM), какие данные ожидать в вашем DataRow.

Ниже приведен рабочий пример с кодом.

yield return Mapper.Map<DataRowAdapter<T>, T>(new DataRowAdapter<T>(row)); 

класс DataRowAdapter:

public class DataRowAdapter<T> 
{ 
    DataRow _dataRow; 

    public DataRowAdapter(DataRow dataRow) 
    { 
     _dataRow = dataRow; 
    } 

    public DataRow Current 
    { 
     get 
     { 
      return _dataRow; 
     } 
    } 
} 

И ваше отображение нового бренда:

 Mapper.Register<DataRowAdapter<ImportedFiles>, ImportedFiles>() 
     .Member(dest => dest.Id, 
       src => DBNull.Value == src.Current["Id"] ? 0 : (double)src.Current["Id"]) 
     .Member(dest => dest.FileName, 
       src => DBNull.Value == src.Current["FileName"] ? String.Empty : (string)src.Current["FileName"]) 
     .Member(dest => dest.Hash, 
       src => DBNull.Value == src.Current["Hash"] ? String.Empty : (string)src.Current["Hash"]) 
     ; 

Done.