【问题标题】:NpgSQLdataReader GetOrdinal throwing exceptions.. any way around?NpgSQLdataReader GetOrdinal 抛出异常.. 有什么办法吗?
【发布时间】:2010-03-04 09:25:21
【问题描述】:

我围绕 NpgSQL 为我通常在项目的 DAL 中使用的一堆方法构建了一个包装器。其中两个,我通常用来直接从 DataReader 填充 DTO。通常在填充辅助方法中,我将实例化 DTO 并遍历将 Datareader 的数据映射到相应属性的属性。填充方法大部分时间都是生成的。

由于我允许许多属性为空或使用 DTO 的默认值,因此我使用了一种方法来检查 dataReader 的数据是否对属性有效,然后再填写属性。所以我会有一个 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));
}

我的填充方法委托给执行查询的任何方法,如下所示:

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 pre 2.02 中工作得很好。 .当调用 GetOrdinal 方法时,如果 dataReader 中不存在该字段,我会简单地返回 -1。在 IsValidString() 中很容易返回 false 并直接跳到下一个属性。检查不存在的字段对性能的影响几乎可以忽略不计。

不幸的是,当字段不存在时,对 NpgSQL 的更改会使 GetOrdinal 引发异常。我有一个简单的解决方法,我将代码包装在 try /catch 中并在 catch 中抛出 false。但是我能感觉到性能受到了打击,尤其是当我进入调试模式时。填写一长串需要几分钟。

据说,NpgSQL 有一个可以添加到连接字符串(兼容性)的参数以支持此方法的向后兼容性,但我从来没有让它正常工作(由于连接格式错误,我总是遇到异常细绳)。无论如何,我正在寻找更好的解决方法的建议。有什么更好的方法可以从数据读取器中填充对象,甚至可以以某种方式解决异常问题?

【问题讨论】:

    标签: c# datareader npgsql


    【解决方案1】:

    我已经为我的问题创建了一个解决方案,它不需要很大的改变,并且呈现出有趣的性能(或者看起来如此)。可能只是一个新的解析库/包装器。

    基本上,我将遍历 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;
        }
    

    我对我的变化进行计时,以查看差异。进行了搜索,返回了 612 个结果。首先,我也查询了数据库两次,考虑到第一次运行查询以及随后与缓存相关的差异(以及非常重要的差异)。我的 FillObject 方法只是创建了要添加到结果列表中的所需对象的新实例。

    • 对对象实例列表的第一次查询:2896K 滴答声
    • 第二次查询(与第一次相同):1141K 滴答声

    然后我尝试使用之前的填充对象

    • 到所需对象列表,填充返回数据或默认值,检查所有对象属性:3323K 滴答声
    • 至所需对象列表,仅检查搜索中返回的对象属性:1127K 滴答声
    • 要列出所需对象,使用查找列表,仅检查返回的字段:1097K 滴答声
    • 要列出所需对象,使用查找列表,检查所有字段(减去一些嵌套属性):1107K 滴答声

    与使用仅限于所需字段的方法相比,我使用的原始代码消耗了近 3 倍的刻度。杀死它的例外情况。

    使用 fillobject 方法的新代码,与仅检查所需字段相比,检查不存在的字段的开销极小。

    这似乎工作得很好,至少现在是这样。可能会尝试寻找一些优化。 任何建议将不胜感激!

    【讨论】:

      猜你喜欢
      • 2011-11-01
      • 2011-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多