EOF或BOF为真,但记录计数大于零

本文关键字:大于 记录 BOF 为真 EOF | 更新日期: 2023-09-27 18:32:41

我在 C# 中使用记录集,因为我的 DLL 将被 VBA 应用程序使用。我正在使用 ADO.NET 从数据库中获取数据并手动填充记录集。这部分工作正常,我使用 MoveFirst(),我可以浏览记录。

但是我需要对数据进行排序,并且在设置记录集的 Sort 属性后,我不能再使用它了。它说 BOF 或 EOF 都是真的,但记录计数接近 300.000,所以我的记录集有数据!为什么在我设置 Sort 属性后会发生这种情况?

无法对数据库进行排序,因为我使用的数据库过程不是我的,我无法访问它。

代码示例:

过程调用和记录集创建:

ADODB.Recordset ExecuteProcedure(string procedure, List<SqlParameter> parameters, List<Alias> alias)
    {
        SqlCommand commando = new SqlCommand(procedure, this.Connection);
        commando.CommandType = CommandType.StoredProcedure;
        commando.CommandTimeout = this.TimeOut;
        if (parameters != null)
        {
            foreach (SqlParameter param in parameters)
            { commando.Parameters.Add(param); }
        };
        SqlDataReader dr = commando.ExecuteReader();
        ADODB.Recordset result = new ADODB.Recordset();
        result.CursorLocation = ADODB.CursorLocationEnum.adUseClient;
        //create columns
        foreach (var item in alias.OrderBy(o => o.ColumnIndex).ToList())
        {
            Type fieldType = null;
            for (int i = 0; i < dr.FieldCount; i++)
            {
                if (dr.GetName(i).Equals(item.ColumnName))
                {
                    fieldType = dr.GetFieldType(i);
                    break;
                }
            }
            result.Fields.Append(item.Alias
                , TranslateType(fieldType)
                , fieldType == typeof(String) ? 16384 : (fieldType == typeof(DateTime) ? 0 : int.MaxValue)
                , ADODB.FieldAttributeEnum.adFldIsNullable
                , null);
        }
        result.Open(System.Reflection.Missing.Value, System.Reflection.Missing.Value
                , ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockOptimistic, 0);
        while (dr.Read())
        {
            result.AddNew(System.Reflection.Missing.Value, System.Reflection.Missing.Value);
            foreach (var item in alias.OrderBy(o => o.ColumnIndex).ToList())
            {
                result.Fields[item.ColumnIndex - 1].Value = dr[item.ColumnName];
            }
        }
        dr.Close();
        return result;
    }

调用方法:

var rs = myAccessManager.ExecuteProcedure("procedure", param, StringToDatatableAlias(colunas));
if (!rs.BOF)
    rs.MoveFirst();
//until this point, I can see de data on Immediate window. Everything is working fine
if(!String.IsNullOrEmpty(orderBy))
    rs.Sort = orderBy;
//after this point, I get the BOF or EOF are both true error when I try to access de data on recordset. But recordcount property is still above 300.000

EOF或BOF为真,但记录计数大于零

我已经找到了问题和解决方案。我在这里写为什么会发生这种情况,以及如何解决将来有人遇到这种情况。

首先,问题是由我创建记录集字段的方式引起的。特别是这一行:

result.Fields.Append(item.Alias
            , TranslateType(fieldType)
            , fieldType == typeof(String) ? 16384 : (fieldType == typeof(DateTime) ? 0 : int.MaxValue)
            , ADODB.FieldAttributeEnum.adFldIsNullable
            , null);

我使用此子句定义了字段长度 fieldType == typeof(String) ? 16384 : (fieldType == typeof(DateTime) ? 0 : int.MaxValue) 字段太大。如此之大,以至于记录集无法排序并给出例外。它只是得到了EOF和BOF =true,记录集变得不可用。

那么我做了什么来解决这个问题呢?我使用了数据库字段中的元数据信息来定义记录集字段的长度。

代码的结尾如下:

ADODB.Recordset ExecuteProcedure(string procedure, List<SqlParameter> parameters, List<Alias> alias)
{
    SqlCommand commando = new SqlCommand(procedure, this.Connection);
    commando.CommandType = CommandType.StoredProcedure;
    commando.CommandTimeout = this.TimeOut;
    if (parameters != null)
    {
        foreach (SqlParameter param in parameters)
        { commando.Parameters.Add(param); }
    };
    SqlDataReader dr = commando.ExecuteReader();
    ADODB.Recordset result = new ADODB.Recordset();
    result.CursorLocation = ADODB.CursorLocationEnum.adUseClient;
    //get table schema
    DataTable schema = dr.GetSchemaTable();
    foreach (var item in alias.OrderBy(o => o.ColumnIndex).ToList())
    {
        Type fieldType = dr.GetFieldType(dr.GetOrdinal(item.ColumnName));
        result.Fields.Append(item.Alias
            , TranslateType(fieldType)
            , Convert.ToInt32(schema.Rows[dr.GetOrdinal(item.ColumnName)]["ColumnSize"])
            , schema.Rows[dr.GetOrdinal(item.ColumnName)]["AllowDBNull"].ToString().ToLower().Equals("true") ? ADODB.FieldAttributeEnum.adFldIsNullable : ADODB.FieldAttributeEnum.adFldUnspecified
            , null);
    }
    result.Open(System.Reflection.Missing.Value, System.Reflection.Missing.Value
            , ADODB.CursorTypeEnum.adOpenStatic, ADODB.LockTypeEnum.adLockOptimistic, 0);

    while (dr.Read())
    {
        result.AddNew(System.Reflection.Missing.Value, System.Reflection.Missing.Value);
        foreach (var item in alias.OrderBy(o => o.ColumnIndex).ToList())
        {
            result.Fields[item.ColumnIndex - 1].Value = dr[item.ColumnName];
        }
    }
    dr.Close();
    return result;
}