Acceso a datos .DBF desde ADO.NET
mediante C# y OLEDB
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