2016-02-01 1 views
1

J'utilise un jeu d'enregistrements en C# parce que ma DLL va être utilisée par une application VBA. Je reçois les données de la base de données en utilisant ADO.NET et en remplissant le jeu d'enregistrements manuellement. Cette partie fonctionne très bien, j'utilise MoveFirst() et je peux naviguer dans les enregistrements.soit eof ou bof est vrai, mais recordcount est supérieur à zéro

Mais j'ai besoin de trier les données et après avoir défini la propriété Sort du jeu d'enregistrements, je ne peux plus l'utiliser. Il est dit que BOF ou EOF sont tous les deux vrais, mais que le nombre d'enregistrements est proche de 300.000 donc mon jeu de données contient des données! Pourquoi cela se produit-il juste après avoir défini la propriété Sort?

Je ne peux pas trier sur la base de données parce que j'utilise une procédure d'une base de données qui n'est pas la mienne, je n'y ai pas accès.

Exemple de code:

appel Proc et à la création d'enregistrements:

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; 
    } 

Appel aux méthodes:

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 
+0

Il n'y a pas de VBA dans votre question. En le taguant incorrectement, vous avez fait perdre du temps à un expert vba sur une question de C#. –

+0

Quelle est la valeur de orderBy? –

+0

@bgalea désolé, vous avez raison – Raiiy

Répondre

1

J'ai trouvé le problème et une solution. J'écris ici pourquoi cela se produisait et comment résoudre si quelqu'un devait rester coincé avec ça dans le futur. Tout d'abord, le problème est dû à la façon dont j'ai créé les champs de jeu d'enregistrements. especifically cette ligne:

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

J'ai défini la longueur des champs en utilisant cette clause fieldType == typeof(String) ? 16384 : (fieldType == typeof(DateTime) ? 0 : int.MaxValue) et les champs étaient trop grands. Si gros que ce jeu d'enregistrements était incapable de trier et de donner une exception. C'est juste EOF et BOF = true et le jeu d'enregistrements est devenu inaccessible.

Alors qu'est-ce que j'ai fait pour résoudre ce problème? J'ai utilisé les informations de métadonnées des champs de base de données pour définir la longueur des champs de jeu d'enregistrements.

Et voici comment la fin du code:

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; 
}