使用 Reflection 和 IDataReader.GetSchemaTable 创建读取和处理 IDataRead
本文关键字:读取 处理 创建 IDataRead GetSchemaTable Reflection IDataReader 使用 | 更新日期: 2023-09-27 18:01:30
我正在编写一个类,该类封装了使用 ADO.NET 从数据库中检索数据的复杂性。其核心方法是
private void Read<T>(Action<T> action) where T : class, new() {
var matches = new LinkedList<KeyValuePair<int, PropertyInfo>>();
// Read the current result set's metadata.
using (DataTable schema = this.reader.GetSchemaTable()) {
DataRowCollection fields = schema.Rows;
// Retrieve the target type's properties.
// This is functionally equivalent to typeof(T).GetProperties(), but
// previously retrieved PropertyInfo[]s are memoized for efficiency.
var properties = ReflectionHelper.GetProperties(typeof(T));
// Attempt to match the target type's columns...
foreach (PropertyInfo property in properties) {
string name = property.Name;
Type type = property.PropertyType;
// ... with the current result set's fields...
foreach (DataRow field in fields) {
// ... according to their names and types.
if ((string)field["ColumnName"] == name && field["DataType"] == type) {
// Store all successful matches in memory.
matches.AddLast(new KeyValuePair<int, PropertyInfo>((int)field["ColumnOrdinal"], property));
fields.Remove(field);
break;
}
}
}
}
// For each row, create an instance of the target type and set its
// properties to the row's values for their matched fields.
while (this.reader.Read()) {
T result = new T();
foreach (var match in matches)
match.Value.SetValue(result, this.reader[match.Key], null);
action(result);
}
// Go to the next result set.
this.reader.NextResult();
}
关于该方法的正确性,不幸的是我现在无法测试,我有以下问题:
当使用单个
IDataReader
从两个或多个结果集中检索数据时,IDataReader.GetSchemaTable
返回所有结果集的元数据,还是只返回与当前结果集对应的元数据?IDataReader.GetSchemaTable
检索的列序号是否等于索引器IDataReader[int]
使用的序号?如果没有,有没有办法将前者映射到后者?
关于该方法的效率,我有以下问题:
DataRowCollection
的底层数据结构是什么?即使这个问题不能回答,至少,使用DataRowCollection.Remove()
从DataRowCollection
中删除DataRow
的渐近计算复杂度是多少?
而且,关于该方法明显的丑陋,我有以下问题:
有没有办法从
IDataReader
中检索特定的元数据(例如,只是列的序号、名称和类型(,而不是完整的模式表?(string)field["ColumnName"] == name
有必要string
演员吗?.NET 如何比较恰好包含对string
引用的object
变量与string
变量:按引用值还是按内部数据值?(当有疑问时,我宁愿在正确性方面犯错,因此演员表;但是,当能够消除所有怀疑时,我更喜欢这样做。即使我使用
KeyValuePair<int, PropertyInfo>
s 来表示匹配字段和属性对,这些对也不是实际的键值对。它们只是普通的普通 2 元组。但是,.NET Framework 的 2.0 版不提供元组数据类型,而且,如果我要创建自己的特殊用途元组,我仍然不知道在哪里声明它。在C++,最自然的地方是在方法内部。但这是 C#,方法内类型定义是非法的。我该怎么办?应对使用根据定义不是最合适的类型(KeyValuePair<int, PropertyInfo>
(的不优雅,或者应对无法在最适合的地方声明类型?
就 A1 而言,我相信在调用 IDataReader.NextResult()
之前,GetSchemaTable
只会返回当前结果集的信息。
然后,当调用NextResult()
时,您必须再次执行GetSchemaTable
以获取有关当前结果集的信息。
呵。
我可以回答其中的几个:
答2(是的,从GetSchemaTable
中得出的列序号与用于索引器的列序号相同。
B1(我不确定,但这没关系,因为如果您在foreach
中枚举时从DataRowCollection
中删除它,您将抛出. 如果我是你,我会制作一个字段或属性的哈希表来帮助匹配它们,而不是担心这种线性搜索和删除。
编辑:我错了,这是一个谎言 - 正如爱德华多在下面指出的那样,它不会抛出。 但是,如果您认为您可能有一个具有几十个以上属性的类型,它仍然有点慢。
C2(是的,这是必要的,否则它将通过引用进行比较。
C3(无论如何,我都倾向于使用KeyValuePair
。