C# } 如果(值为十进制?| |值为十进制) 返回Convert.ChangeType(value,typeof(double)); if(值为字符串) 返回值.ToString().TrimEnd(); 返回值; } 公共重写IEnumerable GetDynamicMemberNames() { 返回列; } 私有void VerifyColumn(字符串名称) { //审查:性能 如果(!Columns.Contains(名称,StringComparer.OrdinalIgnoreCase)) { 抛出新的InvalidOperationException( String.Format(CultureInfo.CurrentCulture, “无效列名”+名称]; } } AttributeCollection ICustomTypeDescriptor.GetAttributes() { 返回AttributeCollection.Empty; } 字符串ICustomTypeDescriptor.GetClassName() { 返回null; } 字符串ICustomTypeDescriptor.GetComponentName() { 返回null; } TypeConverter ICustomTypeDescriptor.GetConverter() { 返回null; } EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { 返回null; } PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { 返回null; } 对象ICustomTypeDescriptor.GetEditor(类型editorBaseType) { 返回null; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents(属性[]属性) { 返回EventDescriptorCollection.Empty; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { 返回EventDescriptorCollection.Empty; } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(属性[]属性) { 返回((ICustomTypeDescriptor)this.GetProperties(); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { //获取每个列名的名称和类型 var properties=来自列中的columnName 让columnIndex=Record.GetOrdinal(columnName) let type=Record.GetFieldType(columnIndex) 选择新的DynamicPropertyDescriptor(columnName,type); 返回新的PropertyDescriptorCollection(properties.ToArray(),只读:true); } 对象ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { 归还这个; } 私有类DynamicPropertyDescriptor:PropertyDescriptor { 私有静态只读属性[]_empty=新属性[0]; 私有只读类型_类型; 公共DynamicPropertyDescriptor(字符串名称、类型) :base(名称,_空) { _类型=类型; } 公共重写类型ComponentType { 获取{return typeof(EevaDynamicRecord);} } 公共覆盖布尔为只读 { 获取{return true;} } 公共覆盖类型PropertyType { 获取{return\u type;} } 公共覆盖布尔CanResetValue(对象组件) { 返回false; } 公共覆盖对象GetValue(对象组件) { EevaDynamicRecord记录=组件为EevaDynamicRecord; //回顾:如果传入了错误的对象,我们是否应该抛出? if(记录!=null) { 返回记录[名称]; } 返回null; } 公共替代无效重置值(对象组件) { 抛出新的InvalidOperationException( String.Format(CultureInfo.CurrentCulture, “DataResources.RecordIsReadOnly”,名称); } 公共覆盖无效设置值(对象组件、对象值) { 抛出新的InvalidOperationException( String.Format(CultureInfo.CurrentCulture, “DataResources.RecordIsReadOnly”,名称); } 公共重写bool ShouldSerializeValue(对象组件) { 返回false; } } } }

C# } 如果(值为十进制?| |值为十进制) 返回Convert.ChangeType(value,typeof(double)); if(值为字符串) 返回值.ToString().TrimEnd(); 返回值; } 公共重写IEnumerable GetDynamicMemberNames() { 返回列; } 私有void VerifyColumn(字符串名称) { //审查:性能 如果(!Columns.Contains(名称,StringComparer.OrdinalIgnoreCase)) { 抛出新的InvalidOperationException( String.Format(CultureInfo.CurrentCulture, “无效列名”+名称]; } } AttributeCollection ICustomTypeDescriptor.GetAttributes() { 返回AttributeCollection.Empty; } 字符串ICustomTypeDescriptor.GetClassName() { 返回null; } 字符串ICustomTypeDescriptor.GetComponentName() { 返回null; } TypeConverter ICustomTypeDescriptor.GetConverter() { 返回null; } EventDescriptor ICustomTypeDescriptor.GetDefaultEvent() { 返回null; } PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty() { 返回null; } 对象ICustomTypeDescriptor.GetEditor(类型editorBaseType) { 返回null; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents(属性[]属性) { 返回EventDescriptorCollection.Empty; } EventDescriptorCollection ICustomTypeDescriptor.GetEvents() { 返回EventDescriptorCollection.Empty; } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(属性[]属性) { 返回((ICustomTypeDescriptor)this.GetProperties(); } PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties() { //获取每个列名的名称和类型 var properties=来自列中的columnName 让columnIndex=Record.GetOrdinal(columnName) let type=Record.GetFieldType(columnIndex) 选择新的DynamicPropertyDescriptor(columnName,type); 返回新的PropertyDescriptorCollection(properties.ToArray(),只读:true); } 对象ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd) { 归还这个; } 私有类DynamicPropertyDescriptor:PropertyDescriptor { 私有静态只读属性[]_empty=新属性[0]; 私有只读类型_类型; 公共DynamicPropertyDescriptor(字符串名称、类型) :base(名称,_空) { _类型=类型; } 公共重写类型ComponentType { 获取{return typeof(EevaDynamicRecord);} } 公共覆盖布尔为只读 { 获取{return true;} } 公共覆盖类型PropertyType { 获取{return\u type;} } 公共覆盖布尔CanResetValue(对象组件) { 返回false; } 公共覆盖对象GetValue(对象组件) { EevaDynamicRecord记录=组件为EevaDynamicRecord; //回顾:如果传入了错误的对象,我们是否应该抛出? if(记录!=null) { 返回记录[名称]; } 返回null; } 公共替代无效重置值(对象组件) { 抛出新的InvalidOperationException( String.Format(CultureInfo.CurrentCulture, “DataResources.RecordIsReadOnly”,名称); } 公共覆盖无效设置值(对象组件、对象值) { 抛出新的InvalidOperationException( String.Format(CultureInfo.CurrentCulture, “DataResources.RecordIsReadOnly”,名称); } 公共重写bool ShouldSerializeValue(对象组件) { 返回false; } } } },c#,asp.net-mvc-4,ado.net,mono,npgsql,C#,Asp.net Mvc 4,Ado.net,Mono,Npgsql,我也在网上发布了这个 更新 创建每个dynamicrecord的副本可能会解决以下问题: Dictionary<string, object> Clonedict; public EevaDynamicRecord Clone() { var res = new EevaDynamicRecord(Columns, Record); res.Clonedict = new Dictionary<string, object>(); for (int

我也在网上发布了这个

更新

创建每个dynamicrecord的副本可能会解决以下问题:

Dictionary<string, object> Clonedict;
public EevaDynamicRecord Clone()
{
    var res = new EevaDynamicRecord(Columns, Record);
    res.Clonedict = new Dictionary<string, object>();
    for (int i = 0; i < Record.FieldCount; i++)
        res.Clonedict[Record.GetName(i)] = Record[i]);
    return res;
    // this also does not work:
    // return (EevaDynamicRecord)this.MemberwiseClone();
}
词典克隆;
公共EevaDynamicRecord克隆()
{
var res=新的EevaDynamicRecord(列、记录);
res.Clonedict=新字典();
对于(int i=0;i

有更好的解决方案吗?

我不知道这是否一定有效,但为了提出建议,我需要发布一个答案,因为它包含一个代码示例

如果我是对的,并且问题是因为您试图在命令超出范围后从读取器访问数据而发生的,那么这将解决这个问题

测试方法替换为以下方法:

    public ActionResult Test()
    {
        var data = TestData().ToArray();
        return View("ReportData", new ReportDataViewModel(data, ""));
    }
    IEnumerable<dynamic> TestData()
    {
        List<dynamic> results = new List<dynamic>();
        using (var connection = new NpgsqlConnection(ConnectionString()))
        {
            connection.Open();

            DbCommand command = (DbCommand)connection.CreateCommand();
            command.CommandText = "select 'A' union select 'B'";

            using (command)
            {
                using (DbDataReader reader = command.ExecuteReader())
                {
                    IEnumerable<string> columnNames = null;

                    while (reader.Read())
                    {
                        if (columnNames == null)
                            columnNames = GetColumnNames(reader);
                        results.Add(new EevaDynamicRecord(columnNames, reader));
                    }
                    //foreach (DbDataRecord record in reader)
                    //{
                    //    if (columnNames == null)
                    //        columnNames = GetColumnNames(record);
                    //    yield return new EevaDynamicRecord(columnNames, record);
                    //}
                }
            }
        }
        return results;
    }
如果没有帮助,请尝试用以下方法替换
TestData
方法:

    public ActionResult Test()
    {
        var data = TestData().ToArray();
        return View("ReportData", new ReportDataViewModel(data, ""));
    }
    IEnumerable<dynamic> TestData()
    {
        List<dynamic> results = new List<dynamic>();
        using (var connection = new NpgsqlConnection(ConnectionString()))
        {
            connection.Open();

            DbCommand command = (DbCommand)connection.CreateCommand();
            command.CommandText = "select 'A' union select 'B'";

            using (command)
            {
                using (DbDataReader reader = command.ExecuteReader())
                {
                    IEnumerable<string> columnNames = null;

                    while (reader.Read())
                    {
                        if (columnNames == null)
                            columnNames = GetColumnNames(reader);
                        results.Add(new EevaDynamicRecord(columnNames, reader));
                    }
                    //foreach (DbDataRecord record in reader)
                    //{
                    //    if (columnNames == null)
                    //        columnNames = GetColumnNames(record);
                    //    yield return new EevaDynamicRecord(columnNames, record);
                    //}
                }
            }
        }
        return results;
    }
IEnumerable TestData()
{
列表结果=新列表();
使用(var connection=newnpgsqlconnection(ConnectionString()))
{
connection.Open();
DbCommand=(DbCommand)connection.CreateCommand();
command.CommandText=“选择“A”并选择“B”;
使用(命令)
{
使用(DbDataReader)读取
// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Dynamic;
using System.Globalization;
using System.Linq;
using System.Text;
using WebMatrix.Data.Resources;

namespace Eeva.Business
{
    public sealed class EevaDynamicRecord : DynamicObject, ICustomTypeDescriptor
    {
        public EevaDynamicRecord(IEnumerable<string> columnNames, IDataRecord record)
        {
            Debug.Assert(record != null, "record should not be null");
            Debug.Assert(columnNames != null, "columnNames should not be null");

            Columns = columnNames.ToList();
            Record = record;
        }

        public IList<string> Columns { get; private set; }

        private IDataRecord Record { get; set; }

        public object this[string name]
        {
            get
            {
                for (int i = 0; i < Record.FieldCount; i++)
                {
                    string normname = Record.GetName(i);
                    if (normname.Equals(name, StringComparison.InvariantCultureIgnoreCase))
                        return GetNonNullValue(i);
                }
                throw new InvalidOperationException("No column " + name);
            }
        }

        public object this[int index]
        {
            get
            {
                return GetNonNullValue(index); // GetValue(Record[index]);
            }
        }

        public string Field(int fldNo)
        {
            return Record.GetName(fldNo).ToUpperInvariant();
        }

        public override bool TryGetMember(GetMemberBinder binder, out object result)
        {
            result = this[binder.Name];
            return true;
        }

        private object GetNonNullValue(int i)
        {
            var value = Record[i];
            if (DBNull.Value == value || value == null)
            {
                var tt = Record.GetFieldType(i).Name;
                switch (tt)
                {
                    case "Decimal":
                    case "Int32":
                    case "Double":
                        return 0;
                    case "String":
                        return "";

                    case "DateTime":
                        return null;

                    case "Boolean":
                        // kui seda pole, siis demos lao kartoteek kartoteegi kaart annab vea:
                        return false;

                }
                return null;
            }
            if (value is decimal? || value is decimal)
                return Convert.ChangeType(value, typeof(double));

            if (value is string)
                return value.ToString().TrimEnd();
            return value;
        }

        public override IEnumerable<string> GetDynamicMemberNames()
        {
            return Columns;
        }

        private void VerifyColumn(string name)
        {
            // REVIEW: Perf
            if (!Columns.Contains(name, StringComparer.OrdinalIgnoreCase))
            {
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentCulture,
                                  "Invalid Column Name " + name));
            }
        }

        AttributeCollection ICustomTypeDescriptor.GetAttributes()
        {
            return AttributeCollection.Empty;
        }

        string ICustomTypeDescriptor.GetClassName()
        {
            return null;
        }

        string ICustomTypeDescriptor.GetComponentName()
        {
            return null;
        }

        TypeConverter ICustomTypeDescriptor.GetConverter()
        {
            return null;
        }

        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        {
            return null;
        }

        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
        {
            return null;
        }

        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
        {
            return null;
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        {
            return EventDescriptorCollection.Empty;
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return EventDescriptorCollection.Empty;
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
        {
            return ((ICustomTypeDescriptor)this).GetProperties();
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
        {
            // Get the name and type for each column name
            var properties = from columnName in Columns
                             let columnIndex = Record.GetOrdinal(columnName)
                             let type = Record.GetFieldType(columnIndex)
                             select new DynamicPropertyDescriptor(columnName, type);

            return new PropertyDescriptorCollection(properties.ToArray(), readOnly: true);
        }

        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }

        private class DynamicPropertyDescriptor : PropertyDescriptor
        {
            private static readonly Attribute[] _empty = new Attribute[0];
            private readonly Type _type;

            public DynamicPropertyDescriptor(string name, Type type)
                : base(name, _empty)
            {
                _type = type;
            }

            public override Type ComponentType
            {
                get { return typeof(EevaDynamicRecord); }
            }

            public override bool IsReadOnly
            {
                get { return true; }
            }

            public override Type PropertyType
            {
                get { return _type; }
            }

            public override bool CanResetValue(object component)
            {
                return false;
            }

            public override object GetValue(object component)
            {
                EevaDynamicRecord record = component as EevaDynamicRecord;
                // REVIEW: Should we throw if the wrong object was passed in?
                if (record != null)
                {
                    return record[Name];
                }
                return null;
            }

            public override void ResetValue(object component)
            {
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentCulture,
                                  "DataResources.RecordIsReadOnly", Name));
            }

            public override void SetValue(object component, object value)
            {
                throw new InvalidOperationException(
                    String.Format(CultureInfo.CurrentCulture,
                                  "DataResources.RecordIsReadOnly", Name));
            }

            public override bool ShouldSerializeValue(object component)
            {
                return false;
            }
        }
    }
}
Dictionary<string, object> Clonedict;
public EevaDynamicRecord Clone()
{
    var res = new EevaDynamicRecord(Columns, Record);
    res.Clonedict = new Dictionary<string, object>();
    for (int i = 0; i < Record.FieldCount; i++)
        res.Clonedict[Record.GetName(i)] = Record[i]);
    return res;
    // this also does not work:
    // return (EevaDynamicRecord)this.MemberwiseClone();
}
    public ActionResult Test()
    {
        var data = TestData().ToArray();
        return View("ReportData", new ReportDataViewModel(data, ""));
    }
    IEnumerable<dynamic> TestData()
    {
        List<dynamic> results = new List<dynamic>();
        using (var connection = new NpgsqlConnection(ConnectionString()))
        {
            connection.Open();

            DbCommand command = (DbCommand)connection.CreateCommand();
            command.CommandText = "select 'A' union select 'B'";

            using (command)
            {
                using (DbDataReader reader = command.ExecuteReader())
                {
                    IEnumerable<string> columnNames = null;

                    while (reader.Read())
                    {
                        if (columnNames == null)
                            columnNames = GetColumnNames(reader);
                        results.Add(new EevaDynamicRecord(columnNames, reader));
                    }
                    //foreach (DbDataRecord record in reader)
                    //{
                    //    if (columnNames == null)
                    //        columnNames = GetColumnNames(record);
                    //    yield return new EevaDynamicRecord(columnNames, record);
                    //}
                }
            }
        }
        return results;
    }