首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用反射和IDataReader.GetSchemaTable创建读取和处理IDataReader当前结果集的通用方法时出现的问题

使用反射和IDataReader.GetSchemaTable创建读取和处理IDataReader当前结果集的通用方法时出现的问题
EN

Stack Overflow用户
提问于 2011-07-08 18:32:12
回答 2查看 546关注 0票数 2

我正在编写一个类,它封装了使用ADO.NET从数据库中检索数据的复杂性。

代码语言:javascript
复制
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();
}

关于该方法的正确性,不幸的是,我现在无法测试它的正确性,我有以下问题:

  1. 当使用单个IDataReader从两个或多个结果集检索数据时,IDataReader.GetSchemaTable是返回所有结果集的元数据,还是仅返回与当前结果集对应的元数据?
  2. IDataReader.GetSchemaTable检索的列序号,与索引器IDataReader[int]使用的序数相等吗?如果没有,有没有办法将前者映射到后者?

关于该方法的效率,我有以下问题:

  1. DataRowCollection的底层数据结构是什么?即使这个问题不能回答eb,至少使用DataRowCollectionDataRowCollection中删除DataRow的渐近计算复杂性是多少?

至于该方法明显的丑陋之处,我有以下问题:

是否有任何方法可以检索特定的元数据(例如,列的序号、名称和类型),而不是完整的模式表,从IDataReader

  • Is转换到(string)field["ColumnName"] == name中的string?.NET如何比较碰巧包含对string的引用到string变量的object变量:通过引用值还是内部数据值?(当我有疑问时,我更愿意错误地站在正确性的一边,这样的转换;但是,当能够消除所有的疑问时,我更愿意这样做。)

  • ,尽管我使用KeyValuePair<int, PropertyInfo>s来表示匹配的字段和属性对,但这些对并不是实际的键值对。它们只是普通的2元组。但是,.NET框架的2.0版本并不提供元组数据类型,而且,如果我要创建自己的专用元组,我仍然不知道在哪里声明它。在C++中,最自然的位置将在方法中。但这是C#,方法中的类型定义是非法的。我该怎么办?处理使用定义上不最合适的类型(KeyValuePair<int, PropertyInfo>)或无法声明最适合的类型的不优雅?
EN

回答 2

Stack Overflow用户

发布于 2011-07-08 18:40:27

我可以回答以下几个问题:

A2)是的,GetSchemaTable中的列序号与索引器使用的列序号相同。

B1)我不确定,但这并不重要,因为如果您在foreach中枚举时从DataRowCollection中删除它,就会抛出它。如果我是你,我会做一个字段或属性的哈希表来帮助匹配它们,而不是担心这个线性搜索和删除。

编辑:I是错的,这是一个谎言--正如爱德华多在下面指出的那样,它不会抛出。但是如果你认为你可能有超过几十个属性的类型的话,它还是有点慢的。

( C2)是的,这是必要的,否则它会通过参考进行比较。

C3)无论如何,我都倾向于使用KeyValuePair

票数 1
EN

Stack Overflow用户

发布于 2011-07-08 18:47:09

至于A1,我相信在IDataReader.NextResult()被启用之前,GetSchemaTable只会返回当前结果集的信息。

然后,当NextResult()被启用时,您将不得不再次执行一个GetSchemaTable来获取有关当前结果集的信息。

HTH。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6628816

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档