FoxPress – Enero 2002

 

Acceso a datos .DBF desde ADO.NET mediante C# y OLEDB

 

http://www.fpress.com/

 

Por Abel Sorzano                                   nave.zip                 
 

ADO .NET es la última versión de la tecnología de acceso a datos de Microsoft. ADO .NET es un conjunto de clases, insertadas en el .NET Framework, que permiten que se interactue con fuentes de datos.

 

ADO .NET puede usar:

 

·   el proveedor SQL Server

·   el proveedor OLEDB

·   el proveedor ODBC

 

   Aquí nos fijaremos en los proveedores OLEDB y ODBC.

 

El Proveedor SQL Server  es la forma más aconsejable de conectarse a una Base de Datos SQL Server (version 7.0 o superior). Usa un protocolo propietario para conectarse a la Base de Datos y se basa en el namespace System.Data.Sqlclient.

 

El Proveedor OLEDB se usa con Bases de Datos que soportan interfaces. ADO.NET entre los que se encuentran SQLOLEDB (Microsoft OLE DB Provider for SQL Server)
,MSDAORA ( Microsoft OLE DB Provider for Oracle),Microsoft.Jet.OLEDB.4.0 (OLE DB Provider for Microsoft Jet) y VFPOLEDB (Provider para Visual FoxPro), entre otros. Se basan en el namespace System.Data.Oledb.

 

El Proveedor ODBC se usan con Bases de Datos que soportan accesos a datos mediante ODBC. Este proveedor no viene incluido en la Beta 2 inglesa del .NET Framework y te lo tienes que bajar de http://msdn.microsoft.com/downloads/default.asp?url=/downloads/sample.asp?url=/msdn-files/027/001/668/msdncompositedoc.x La instalación te incorpora el fichero System.Data.ODBC.DLL que te da acceso al namespace System.Data.ODBC

 

Siempre que se pueda es mejor usar el driver OLE DB que el ODBC debido a que es más rápido y además soporta un mayor número de instrucciónes. Por ejemplo según se indica en el "Supported ODBC grammar", el driver ODBC soporta 10 de los SET’s de VFP mientras que el driver OLE DB de VFP parece que es una versión light de la runtime pues soporta 333 (sí, los he contado) comandos y funciones que son nativas de VFP, y entre esas incluye el DO <programa>, SET PROCEDURE TO, transacciones, nativo Fox SQL, crear tablas son libres o parte una Base de Datos (no he visto si se puede CREATE CURSOR  o no). No soporta el DEFINE CLASS o el SET CLASSLIB TO. Viendo este poder, se comprende que sólo los que tienen VFP tengan el driver.

 

          La forma más natura de conectarse al Proveedor OLEDB es mediante el uso de OleDbConnection. OleDbConnection realiza una simple conexión a la Base de Datos, y según las características de la Base de Datos te da el poder de manipularla. Para cerrar la conexión se debe de usar el método close() del objeto.

 

 


 

 


Una vez conectados en  .NET, hay 3 formas de acceder a las datos de una Base de Datos:

·         DataSet

·         DataReader

·         ExecuteNonquery

 

El DataSet,  es parecido a los recordset,  y suele ser el resultado de una consulta SQL. Con el DataSet se toman un conjunto de datos y a continuación se desconecta inmediatamente de la Base de Datos para liberar recursos. Esto signigica que si haces cambios en el DataSet tienes inmediantemente que grabar esos cambios en la Base de Datos. En esto casos se debe complementar el DataSet con el DataAdapter.

El segundo método es usar un DataReader, es un recordset con un cursor  forward-only.  Permanete conectado a la Base de Datos  y se debe de usar en conjunción con un OleDbCommand.

 

El tercer método se llama ExecuteNonQuery. Se usa para ejecutar una instrucción SQL que no devuelve nada, algo similar al "db.execute(sql)" de los clásicos ASP. Se debería de usar un OleDbCommand cuando se use un DataReader.

 

Un ejemplo de cada uno se muestra a continuación. En primer lugar tienes que indicar la cadena de conexión:

 

Acceso a Datos mediante DataSet

 

/////////////////////////////////////////////////

// Ejemplo #1: Acceso a datos mediante DataSet //

// Fichero nuevo2.cs                          //

/////////////////////////////////////////////////

using System;

using System.Data;

 

class TestClass

       {

       static void Main(string[] args)

              {

              OleDbConnection con=new OleDbConnection("Provider=VFPOLEDB.1 ;Data Source=E:\\revista\\OLE2\\libreria.dbc");

                           

              DataSet ds = new DataSet();

              string sql = "select * from Libros";

              OleDbDataAdapter da = new OleDbDataAdapter(sql,con);

              da.Fill(ds,"miTabla");

 

              // Imprime las columnas

              foreach(DataRow dr in ds.Tables[0].Rows)

              {

              Console.WriteLine();

 

              //Muestra el contenido de la primera columna

              Console.WriteLine(dr["Autor"]);

 

              //Muestra el contenido de la segunda columna

              Console.WriteLine(dr["BookTitle"]);

 

              }

              con.Close();

              con.Dispose();

 

              Console.ReadLine();

              }

       }

 

En este código fijate en:

 

1.- la cadena de conexión a la Base de Datos Fox tiene un path fijo que deberás cambiar.

2.- Los directorios del path de acceso a la base de datos se separan con dos // esto es debido a que un solo / es un codigo de escape que es interpretado por C# y por eso hay que poner dos.

3.- La Base de Datos se llama librería.dbc y tiene una sola tabla con 2 campos carácter llamados Autor y BookTitle y un campo numerico llamado Bookid

4.- Este código tienes que compilarlo ejecutando desde una ventana DOS el siguiente código:

csc /out:nuevo2.exe /R:System.Data.DLL;System.Data.Odbc.Dll;System.DLL nuevo2.cs

 

Acceso a Datos mediante DataReader

 

////////////////////////////////////////////////////

// Ejemplo #1: Acceso a datos mediante DataReader //

// Fichero nuevo1.cs                               //

////////////////////////////////////////////////////

using System;

using System.Data.OleDb;

 

class TestClass

       {

       static void Main(string[] args)

              {

              OleDbConnection con=new OleDbConnection("Provider=VFPOLEDB.1 ;Data Source=E:\\revista\\OLE2\\libreria.dbc");

 

              con.Open();

             

              OleDbCommand cmd=con.CreateCommand();

              cmd.CommandText="select * from Libros";

              OleDbDataReader Reader=cmd.ExecuteReader();

             

              // Imprime las columnas

               while (Reader.Read())

              {

              Console.WriteLine("\t{0}\t{1}", Reader.GetInt32(0), Reader.GetString(1));

              }

 

              Reader.Close();

 

              con.Close(); con.Dispose();

 

              Console.ReadLine();

              }

       }

En este código fíjate:

1.- Los accesos a la Base de Datos también tienes que cambiarlos y ponerles los // como en el ejemplo anterior.

2.- Se usa un OledbCommand

3.- En este caso nos traemos la columna primera y la segunda de la Base de Datos. Como la primera es numerica tenemos que leerla con el GetInt32

 

Acceso a Datos mediante ExecuteNonQuery

            ExeCuteNonQuery no se trae los registros sino que te informa del número de registros afectados por la ultima sentencia SQL. Sería algo parecido al _Tally.

/////////////////////////////////////////////////////////

// Ejemplo #1: Acceso a datos mediante ExecutenonQuery //

// Fichero nuevo4.cs                                    //

/////////////////////////////////////////////////////////

using System;

using System.Data;

using System.Data.OleDb;

 

class TestClass

       {

       static void Main(string[] args)

              {

              OleDbConnection con=new OleDbConnection("Provider=VFPOLEDB.1 ;Data Source=E:\\revista\\OLE2\\libreria.dbc");

                           

              string sql = "select * from Libros";

 

              OleDbCommand cmd = new OleDbCommand(sql,con);

              cmd.Connection.Open();

              int numRowsAffected = cmd.ExecuteNonQuery(); // devuelve 0 si ninguno es afectado

 

              {

      Console.WriteLine(numRowsAffected);

              }

 

              con.Close();

              con.Dispose();

              cmd.Connection.Close();

              Console.ReadLine();

              }

       }

En este código fíjate:

1.- Que también se usa el OleDbcommand.

2.- En este caso, al haber hecho una Select nos devuelve el total de registros de esa tabla.

 

Acceso a datos mediante ODBC

En este caso no se usa Ole Db pero lo inclyo por el interés que se pueda presentar para acceder a ese tipo de acceso a datos.

 

using System.Data.Odbc;

using System.Data ;

using System;

 

namespace consum

{

       class Class1

       {

              static void Main(string[] args)

              {

                     try

                     {

                     string tConnectionString = "DSN=miFox;UID=;PWD=;SourceDB=E:\\revista\\ole2\\libreria.dbc;SourceType=DBC;";

                     OdbcConnection tConnection = new OdbcConnection(tConnectionString);

                            string tSQLString = "SELECT * FROM Libros";

                            OdbcCommand tOdbcCommand = new OdbcCommand(tSQLString, tConnection);

                            tConnection.Open();

                            OdbcDataReader tOdbcDataReader =

                                   tOdbcCommand.ExecuteReader(CommandBehavior.SequentialAccess);

                            while (tOdbcDataReader.Read())

                            {

                                  Console.WriteLine(tOdbcDataReader.GetString(0) + " " +

                                                          tOdbcDataReader.GetString(1));

                            }

                            tConnection.Close();

                     }

            catch (OdbcException pOdbcException)

            {

                Console.WriteLine(pOdbcException.StackTrace);

                for (int i=0; i < pOdbcException.Errors.Count; i++){

                    Console.WriteLine("Index #" + i);

                    Console.WriteLine("Message: " +

                                      pOdbcException.Errors[i].Message);                   

                    Console.WriteLine("Native: " +

                                      pOdbcException.Errors[i].NativeError.ToString());

                    Console.WriteLine("Source: " +

                                      pOdbcException.Errors[i].Source);

                    Console.WriteLine("SQL: " +

                                      pOdbcException.Errors[i].SQLState);

                }

            }

                     System.Threading.Thread.Sleep(15000);

        }

       }

}

 

En este código fíjate:

1.- La cadena de conexión es distinta (tiene otro formato)

2.-  Hemos tenido que cargar el namespace de ODBC

3.- Se ha añadido un código, que no sería estricatamente necesario, para controlar los errores y un sleep (dormir) de 15000 segundos.

 

Un  mantenimiento navegacional

Una vez mostrado la forma de acceder a los datos. Adjunto un pequeño mantenimiento en C# basado en ADO.NET mediante el DataSet y datos Fox. No voy a trascribir todo el código, sólo la pantalla resultante y el código de Acceso a los Datos

 


La sustancia del código es el siguiente:

 


   public void GetConnected()

       {

         //OleDbConnection myConn;

         try{

              //Hace un OleDbConnection

              string strCon="Provider=VFPOLEDB.1 ;Data Source=E:\\revista\\OLE\\libreria.dbc" ;

             

              OleDbConnection myConn     =new OleDbConnection(strCon) ;

              string strCom="SELECT * FROM libros" ;

              //construye un  DataSet

              myDataSet = new DataSet() ;

                                 

              myConn.Open() ;

              //Usa el OleDbDataAdapter para ejecutar la consulta

              OleDbDataAdapter myCommand = new OleDbDataAdapter(strCom,myConn) ;

              //Llena el Data Set con la tabla Libros

              myCommand.Fill(myDataSet,"bookstock") ;

              //Cierra el OleDbConnection

              myConn.Close() ;

         }

         catch(Exception e)

         {

              MessageBox.Show("Error al conectarse! "+e.ToString(), "Error");                         

         }

 

El resto es interesante desde el punto de vista de C# y lo tienes en los fuentes.

 

Como lo hacemos por código, hay que escribir todo, como cada uno de los controles:

 

primero.Location = new System.Drawing.Point(24, 312);

         primero.ForeColor = System.Drawing.Color.White;

         primero.Size = new System.Drawing.Size(40, 24);

         primero.TabIndex = 5;

         primero.Font = new System.Drawing.Font("Microsoft Sans Serif", 8f, System.Drawing.FontStyle.Bold);

         primero.Text = "|<<";

         primero.Click += new System.EventHandler(GoFirst);

 

Y también los métodos de los controles:

 

///    Para navegar al BindingManagerBase, incrementa la Posición de la propiedad.

      

       private void MoveNext()

       {  

         if (myBind.Position == myBind.Count -1)

              MessageBox.Show("Fin de los registros");

      else

        myBind.Position += 1;

       }   

 

 

Este código lo puedes compilar desde una ventana DOS con la instrucción:

 

csc /t:winexe /out:Visor.exe /R:System.Data.DLL;System.Windows.Forms.dll;System.DLL Visor.cs

 

 

 

 

FoxPress – Enero de 2002

© 2002 FoxPress. All rights reserved