2010-02-12 2 views
1

Я построил обертку вокруг NpgSQL для кучи методов, которые я обычно использую в DAL моих проектов. Два из них, я обычно использую для заполнения DTO прямо из DataReader. Обычно в методе fill helper я создам DTO и перебираю свойства, сопоставляющие данные Datareader с соответствующим свойством. Метод заполнения генерируется большую часть времени.NpgSQLdataReader GetOrdinal исключение бросания .. любым способом?

Поскольку я допускаю, что многие свойства являются нулевыми или используют значения по умолчанию DTO, я использовал метод, чтобы проверить, действительны ли данные dataReader для свойства перед заполнением prperty. Так что я буду иметь IsValidString («FIELDNAME») и DRGetString («FIELDNAME») методы, например так:

public bool IsValidString(string fieldName) 
{ 
     if (data.GetOrdinal(fieldName) != -1 
      && !data.IsDBNull(data.GetOrdinal(fieldName))) 
      return true; 
     else 
      return false; 
} 

public string DRGetString(string fieldName) 
{ 
     return data.GetString(data.GetOrdinal(fieldName)); 
} 

Мой метод заливки delagated к тому, что метод выполняется запрос и выглядит следующим образом:

public static object FillObject(DataParse<PostgreSQLDBDataParse> dataParser) 
{ 
    TipoFase obj = new TipoFase(); 

    if (dataParser.IsValidInt32("T_TipoFase")) 
     obj.T_TipoFase = dataParser.DRGetInt32("T_TipoFase"); 

    if (dataParser.IsValidString("NM_TipoFase")) 
     obj.NM_TipoFase = dataParser.DRGetString("NM_TipoFase"); 

      //...rest of the properties .. this is usually autogenerated by a T4 template 

    return obj; 
} 

Это работало отлично и dandy в NpgSQL pre 2.02. , Когда был вызван метод GetOrdinal, и если это поле не было в файле dataReader, я бы просто получил -1. Легко вернуть false в IsValidString() и просто перейти к следующему свойству. Эффект, полученный от проверки несуществующих полей, практически не учитывался.

К сожалению, изменения в NpgSQL заставляют GetOrdinal вызывать исключение, когда поле не существует. У меня есть простой способ обхода, в котором я обертываю код в try/catch и ложь в catch. Но я чувствую удар в производительности, особенно когда я иду в режим отладки. Заполнение длинного списка занимает несколько минут.

Предположительно, NpgSQL имеет параметр, который можно добавить к строке соединения (совместимость) для поддержки обратной компоновки для этого метода, но у меня никогда не было этого, чтобы работать правильно (я всегда получаю исключение из-за сформированного mal строка подключения). Во всяком случае, я ищу предложения для улучшения обходных решений. Любой лучший способ заполнить объект из datareader или даже каким-то образом решить проблему с исключением?

ответ

0

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

В основном, я буду перебирать поля dataReader и копировать их в коллекцию (в моем случае список). Затем я проверю правильные данные и, если они будут считаться действительными, я скопирую данные в свойство объекта.

Так что я буду иметь:

public class ParserFields 
{ 
    public string FieldName { get; set; } 
    public Type FieldType { get; set; } 
    public object Data { get; set; } 
} 

и я заполнить объект с помощью:

public static object FillObjectHashed(DataParse<PostgreSQLDBDataParse> dataParser) 
    { 
     //The the Field list with field type and data 
     List<ParserFields> pflist = dataParser.GetReaderFieldList(); 

     //create resulting object instance 
     CandidatoExtendido obj = new CandidatoExtendido(); 

     //check for existing field and valid data and create object 
     ParserFields pfdt = pflist.Find(objt => objt.FieldName == "NS_Candidato"); 
     if (pfdt != null && pfdt.FieldType == typeof(int) && pfdt.Data.ToString() != String.Empty) 
      obj.NS_Candidato = (int)pfdt.Data; 

     pfdt = pflist.Find(objt => objt.FieldName == "NM_Candidato"); 
     if (pfdt != null && pfdt.FieldType == typeof(string) && pfdt.Data.ToString() != String.Empty) 
      obj.NM_Candidato = (string)pfdt.Data; 

     pfdt = pflist.Find(objt => objt.FieldName == "Z_Nasc"); 
     if (pfdt != null && pfdt.FieldType == typeof(DateTime) && pfdt.Data.ToString() != String.Empty) 
      obj.Z_Nasc = (DateTime)pfdt.Data; 

     //... 

     return obj; 
    } 

Я приурочены свои варианты, чтобы увидеть diferences. Был поиск, который возвратил 612 результатов. Сначала я запросил базу данных дважды, чтобы учесть первый запуск запроса и последующие различия, связанные с кешированием (и тем, что довольно значительным). Мой метод FillObject просто создал новый экземпляр желаемого объекта, который будет добавлен в список результатов.

  • первого запрос в список экземпляров объекта: 2896K клещи
  • второго запроса (такой же, как первый): 1141K клещей

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

  • В список нужного объекта, заполненный данными возврата или значениями по умолчанию, проверяя все свойства объектов: 3323K клещей
  • В список желаемых объектов, проверка свойств только объект вернулся в поиске: 1127K клещей
  • Чтобы список желаемых объектов, используя список поиска, проверки только возвращаемые поля: 1097K тиков
  • Чтобы получить список желаемых объектов, используя список поиска, проверки всех полей (минус несколько вложенных свойств): 1107K клещей

Оригинальный код, который я использовал, потреблял почти в 3 раза больше тиков, чем при использовании метода, ограниченного желаемыми полями. Преступления, где его убивают.

С новым кодом метода fillobject накладные расходы на проверку inexistente files минимальны по сравнению с проверкой только на нужные поля.

Это, кажется, работает хорошо, на данный момент, по крайней мере. Могу попытаться найти пару оптимизаций. Любой sugestion будет оценен!

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

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