2010-02-12 48 views
1

我在我的項目DAL中通常使用的一堆方法構建了一個圍繞NpgSQL的包裝。其中兩個,我通常用來從DataReader直接填充DTO。通常在填充幫助器方法中,我將實例化DTO並遍歷將數據報告者的數據映射到相應屬性的屬性。大部分時間都會生成填充方法。NpgSQLdataReader GetOrdinal拋出異常..任何方式?

由於我允許許多屬性爲空或使用DTO的默認值,我已經使用了一種方法來檢查dataReader的數據在填寫屬性之前是否對屬性有效。所以我有一個IsValidString(「字段名」)和DRGetString(「字段名」)方法,像這樣:

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; 
} 

這是在NpgSQL預2.02工作正常和丹迪。 。當調用GetOrdinal方法時,如果該字段在dataReader中不存在,我只會返回-1。容易在IsValidString()中返回false,並簡單地跳到下一個屬性。檢查不實際領域的表現實際上是可以忽略的。

不幸的是,當字段不存在時,對NpgSQL的更改會使GetOrdinal引發異常。我有一個簡單的解決方法,在try/catch中包裝代碼並在catch中拋出false。但是我可以感受到性能方面的衝擊,特別是當我進入調試模式時。填寫一個長列表需要幾分鐘。

此外,NpgSQL有一個參數可以添加到連接字符串(Compatability)以支持這種方法的後向兼容性,但我從來沒有得到這個工作正常(我總是得到一個異常,因爲形成了一個錯誤連接字符串)。無論如何,我正在尋找更好的解決方法。有什麼更好的方式來填寫datareader中的對象,或者甚至以某種方式解決異常問題?

回答

0

我已經爲我的問題創建了一個解決方案,它不需要很大的改變,並且呈現有趣的性能(或者看起來似乎如此)。可能只是一個新的解析庫/包裝。

基本上,我將遍歷dataReader的字段,並將每個複製到一個集合(在我的情況下是一個List)。然後我會檢查有效數據,如果認爲有效,我會將數據複製到對象的屬性。

那麼我會有:

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; 
    } 

我計時我的變化,看到個體差異。搜索結果是否返回612。首先,我查詢數據庫兩次也考慮了查詢的第一次運行和後續與緩存相關的差異(以及相當重要的地方)。我的FillObject方法只是簡單地創建了一個新的想要添加到結果列表中的對象的實例。

  • 1查詢對象的實例列表:2896K
  • 第二查詢(同前):1141K

然後我使用以前的填充對象

嘗試
  • 到希望的對象列表,填充返回數據或默認值,檢查所有的對象屬性:3323K
  • 要列出所需的對象,僅檢查對象的屬性搜索中返回:1127K
  • 所需對象列表,使用查找列表中,僅檢查返回的字段:1097K
  • 要列出所需的對象的,使用查找表,檢查所有的字段(減去幾個嵌套屬性)的:1107K

原我使用的代碼比使用僅限於所需字段的方法消耗了近3倍的時間。殺死它的消息。

使用fillobject方法的新代碼,與只檢查所需字段相比,用於檢查簡單文件的開銷很小。

這似乎很好,現在至少。可能會嘗試尋找幾個優化。 任何消化,將不勝感激!