我为NpgSQL构建了一个包装器,用于我在项目的DAL中经常使用的一些方法。其中两个,我通常用来直接从DataReader填充DTO。通常在填充辅助方法中,我将实例化DTO并迭代将Datareader的数据映射到相应属性的属性。填充方法大部分时间都是生成的。
由于我允许许多属性为null或使用DTO的默认值,因此我在填写prperty之前使用了一种方法来检查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有一个参数可以添加到连接字符串(Compatability)以支持此方法的向后兼容性,但是我从来没有这样做才能正常工作(由于形成连接错误,我总是得到一个例外串)。无论如何,我正在寻找更好的解决方法的建议。有没有更好的方法从datareader填充对象,甚至以某种方式解决异常问题?
答案 0 :(得分:0)
我已经为我的问题创建了一个解决方案,它不需要很大的改动,并且呈现出有趣的性能(或者看起来似乎如此)。可能只是一个新的解析库/包装器。
基本上,我将遍历dataReader的字段,并将每个字段复制到Collection(在我的例子中是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方法只是创建了一个新的实例,用于添加到结果列表中的所需对象。
然后我尝试使用以前的填充对象
我使用的原始代码消耗了比使用限制在所需字段的方法多3倍的刻度。杀死它的重复。
使用fillobject方法的新代码,与仅检查所需字段相比,检查不存在文件的开销最小化。
这似乎很好,至少现在。可能会尝试寻找几个优化。 任何消化都将不胜感激!