2010-02-12 129 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方法的新代码,与只检查所需字段相比,用于检查简单文件的开销很小。

这似乎很好,现在至少。可能会尝试寻找几个优化。 任何消化,将不胜感激!