C# - Acessar um arquivo DBF e copiar para o SQL Server
Neste artigo vamos recordar como acessar um arquivo no formato DBF e copiar o seu conteúdo para um banco de dados SQL Server usando a linguagem C#. |
Em pleno século XXI quem é que precisaria acessar um arquivo DBF ?
Pode estar certo que se você procurar vai encontrar muitos aplicativos rodando que ainda acessam arquivos DBF, e, ola que não serão poucos.
A resposta pode ser surpreendente e os motivos também mas vamos deixar essa discussão de lado e passar para a parte prática.
E agora, oque fazer se você precidar acessar, ler e exportar o contéudo de um DBF ? Por onde começar ???
Bem, você poderia usar o DBase, FoxPro , um utilitário de terceiros, etc., etc. Mas neste artigo vamos usar apenas código C#.
Para escrever reste artigo eu coletei informações de diversos sites da Web cujas referências estão no final do artigo.
A seguir vou elencar as ferramentas que foram usadas :
Gostaria de avisar que o acesso foi feito em um arquivo no formato DBF do FoxPro, para outros formatos eu não testei e não garanto que o código vai funcionar.
A figura abaixo mostra as etapas que iremos realizar :
Chega de papo e vamos ao trabalho...
Selecionando os arquivos DBF de exemplo
Acesse o link https://github.com/infused/dbf/tree/master/spec/fixtures e baixe os arquivos :
E copie os arquivos para uma mesma pasta no seu computador. Neste artigo esses arquivos estarão na pasta c:\dados\dbf.
Definindo o banco de dados SQL Server
Neste artigo eu vou criar uma tabela em um banco de dados SQL Server para armazenar os dados do arquivo DBF. Para tornar o código mais simples eu vou escolhar um banco de dados SQL Server existente chamado CadastroDB.mdf para armazenar a tabela.
Você pode escolher qualquer outro banco de dados, e, pode ainda criar via código o banco de dados.
A string de
conexão do banco de dados CadastroDB.mdf usada
neste artigo é a seguinte :
"Data Source=.;Initial Catalog=CadastroDB;Integrated
Security=SSPI";
Criando um projeto Windows Forms no VS 2017 Community
Criar um novo projeto Windows Desktop usando o template Windows Forms App(.NET Framework) usando o VS 2017 Community com o nome WF_LeSalva_Dbf;
A partir da ToolBox inclua no formulário Form1.cs os controles:
Disponha os controles conforme o leiaute da figura abaixo:
Antes de prosseguir não esqueça de instalar o driver do provedor Visual FoxPro OLE DB Provider.
Definindo o código do formulário Form1.cs:
Namespaces usados
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;
using System.IO;
using System.Text;
using System.Windows.Forms;
A seguir vamos definir variáveis que iremos usar no formulário :
DataTable dtData, dtColumn;
string nomeArquivoDbf = @"c:\dados\dbf\contacts.dbf";
string conString = "Data Source=.;Initial Catalog=CadastroDB;Integrated Security=SSPI";
public IList<DbfFieldDescriptor> FieldDescriptors { get; set; }
|
No evento Click do botão - Acessar e Exportar dados do arquivo DBF - inclua o código que vai chamar o método para acessar e ler o arquivo DBF:
private void btnLerDBF_Click(object sender, EventArgs e)
{
try
{
LeArquivoDBF();
}
catch (Exception ex)
{
MessageBox.Show("Erro :" + ex.Message);
}
}
|
Código do método LeArquivoDBF
Este método acessa o arquivo DBF e le os seus dados usando o provedor VFPOLEDB1 e define um DataTable em memória para copiar as informações do DBF:
private void LeArquivoDBF()
{
string caminhoArquivoDbf = Path.GetDirectoryName(nomeArquivoDbf);
OleDbConnection connection = new OleDbConnection("Provider=VFPOLEDB.1;Data Source="
+ caminhoArquivoDbf + ";");
connection.Open();
DataTable tables = connection.GetSchema(OleDbMetaDataCollectionNames.Tables);
dtColumn = null;
string fName = Path.GetFileNameWithoutExtension(nomeArquivoDbf);
foreach (DataRow rowTables in tables.Rows)
{
if (rowTables["table_name"].ToString().ToUpper() == fName.ToUpper())
{
DataTable columns = connection.GetSchema(OleDbMetaDataCollectionNames.Columns,
new String[] { null, null, rowTables["table_name"].ToString(), null });
dtColumn = GetColumnDataTable();
foreach (System.Data.DataRow rowColumns in columns.Rows)
{
DataRow dr = dtColumn.NewRow();
dr[0] = rowColumns["column_name"].ToString();
dr[1] = OleDbType(int.Parse(rowColumns["data_type"].ToString()));
dr[2] = rowColumns["data_type"].ToString();
dr[3] = rowColumns["numeric_precision"].ToString();
dtColumn.Rows.Add(dr);
}
break;
}
}
string sql = "SELECT * FROM " + arquivoDBF;
OleDbCommand cmd = new OleDbCommand(sql, connection);
OleDbDataAdapter oledbAdapter = new OleDbDataAdapter(cmd);
dtData = new DataTable();
oledbAdapter.Fill(dtData);
connection.Close();
EscreveDadosDatabaseSQLServer(dtData, dtColumn);
}
|
O método GetColumnDataTable() é usado para definir as colunas da tabela:
static DataTable GetColumnDataTable()
{
DataTable tabela = new DataTable();
tabela.Columns.Add("NAME", typeof(string));
tabela.Columns.Add("TYPE", typeof(string));
tabela.Columns.Add("TYPENO", typeof(string));
tabela.Columns.Add("DEC", typeof(string));
return tabela;
}
|
O método OleDbType() é usasdo para identificar o datatype usado no DBF e retornar o equivalente:
public string OleDbType(int type)
{
string dataType;
switch (type)
{
case 10:
dataType = "BigInt";
break;
case 128:
dataType = "Byte";
break;
case 11:
dataType = "Boolean";
break;
case 8:
dataType = "String";
break;
case 129:
dataType = "String";
break;
case 6:
dataType = "Currency";
break;
case 7:
dataType = "DateTime";
break;
case 133:
dataType = "DateTime";
break;
case 134:
dataType = "TimeSpan";
break;
case 135:
dataType = "DateTime";
break;
case 14:
dataType = "Decimal";
break;
case 5:
dataType = "Double";
break;
case 3:
dataType = "Integer";
break;
case 201:
dataType = "String";
break;
case 203:
dataType = "String";
break;
case 204:
dataType = "Byte";
break;
case 200:
dataType = "String";
break;
case 139:
dataType = "Decimal";
break;
case 202:
dataType = "String";
break;
case 130:
dataType = "String";
break;
case 131:
dataType = "Decimal";
break;
case 64:
dataType = "DateTime";
break;
default:
dataType = "";
break;
}
return dataType;
}
|
Código do método EscreveDadosDataBaseSQLServer
Ao final após ler os dados do DBF e preencher o DataTable em memória o método EscreveDadosDatabaseSQLServer() é chamado.
public void EscreveDadosDatabaseSQLServer(DataTable
dtData, DataTable dtCol) { string nomeTabela = Path.GetFileNameWithoutExtension(nomeArquivoDbf); string caminhoArquivo = nomeArquivoDbf; SqlConnection dbCon = new SqlConnection(conString);
if (dbCon.State == ConnectionState.Closed)
string strQuery = "IF (EXISTS (SELECT * FROM
INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'" + nomeTabela + "'))
BEGIN SELECT 1 END ELSE BEGIN SELECT 0 END";
int valReturn = int.Parse(tabelaExiste.Rows[0][0].ToString()); |
Este código verifica se a tabela com o mesmo nome do DBF existe e a seguir chama o método ReadFileStream que vai definir os descritores dos campos.
void ReadFileStream(string
caminhoArquivo, DataTable dtCol) { FileStream fileStream = new FileStream(caminhoArquivo, FileMode.Open, FileAccess.Read, FileShare.Read); BinaryReader binaryReader = new BinaryReader(fileStream);
var descritoresDeCampos = new
List<DbfFieldDescriptor>(); |
Cada descritor de campo para uma coluna é obtido via método ReadFieldDescriptor() com o código a seguir:
DbfFieldDescriptor ReadFieldDescriptor(BinaryReader br, int fdNo, DataTable dtCol)
{
var campoDescritor = new DbfFieldDescriptor();
campoDescritor.No = fdNo;
string nome = "";
if (fdNo > 0 && fdNo <= dtCol.Rows.Count)
nome = dtCol.Rows[fdNo - 1][0].ToString();
try
{
var fieldNameBytes = new byte[11];
fieldNameBytes[0] = br.ReadByte();
if (fieldNameBytes[0] == 0x0D)
return null; // 0x0D significa fim da lista de campo descritor
br.Read(fieldNameBytes, 1, 10);
campoDescritor.Name = nome;
campoDescritor.TypeChar = (char)br.ReadByte();
br.ReadByte(); // reservado
br.ReadByte(); // reservado
br.ReadByte(); // reservado
br.ReadByte(); // reservado
campoDescritor.Length = br.ReadByte();
campoDescritor.DecimalCount = br.ReadByte();
br.ReadBytes(2);
br.ReadByte();
br.ReadBytes(10);
br.ReadByte();
return campoDescritor;
}
catch (Exception e)
{
if (string.IsNullOrWhiteSpace(campoDescritor.Name))
throw new Exception($"Falha ao ler o campo descritor #{fdNo + 1}", e);
else
throw new Exception($"Falha ao ler o campo descritor #{fdNo + 1} ({campoDescritor.Name})", e);
}
}
|
Para obter os descritores dos campos para as colunas vamos criar uma classe chamada DbfFieldDescriptor com o código abaixo:
using System;
namespace WF_LeSalva_Dbf
{
public class DbfFieldDescriptor
{
public int No { get; set; }
public string Name { get; set; }
public char TypeChar { get; set; }
public int Length { get; set; }
public byte DecimalCount { get; set; }
public string GetSqlDataType()
{
switch (TypeChar)
{
case 'C':
return $"VARCHAR({Length})";
case 'I':
return "INT";
case 'N':
return $"DECIMAL({Length + 1}, {DecimalCount})";
case 'L':
return "BIT";
case 'B':
return "BIT";
case 'D':
return "DATETIME";
case 'M':
return "VARCHAR(MAX)";
case 'S':
return "VARCHAR(MAX)";
case 'T':
return "DATETIME";
case 'W': //?
return "VARCHAR(MAX)";
case '0':
return "INT";
case 'G':
return "VARCHAR(MAX)";
case 'F':
return "FLOAT";
case 'Y':
return "NUMERIC(18,4)";
default:
throw new NotSupportedException();
}
}
}
}
|
Código do método
SalvaDadosNoDatabaseSqlServer
Este método salva os dados na tabela criada no banco de dados e exibe os dados
no DataGridView:
// salva os registros na tabela do banco de dados
public void SalvaDadosNoDatabaseSqlServer(DataTable dtTabela, string nomeTabela, DataTable dtColumn)
{
if (dtTabela.Rows.Count > 0)
{
SqlConnection dbCon = new SqlConnection(conString);
for (int n = 0; n < dtTabela.Rows.Count; n++)
{
if (dbCon.State == ConnectionState.Closed)
dbCon.Open();
string strSql = "";
strSql = "INSERT INTO [" + nomeTabela + "] VALUES(";
for (int i = 0; i < dtColumn.Rows.Count; i++)
{
if (i == dtColumn.Rows.Count - 1)
{
if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "boolean" ||
dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "logical")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'False','true')";
else
strSql = strSql + "'" + dtTabela.Rows[n][i].ToString() + "','true')";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "string")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'','true')";
else
strSql = strSql + "'" + dtTabela.Rows[n][i].ToString().Replace("'", "") + "','true')";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "byte")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'0','true')";
else
strSql = strSql + "'" + Encoding.ASCII.GetBytes(dtTabela.Rows[n][i].ToString()) + "','true')";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "character")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'','true')";
else
strSql = strSql + "'" + dtTabela.Rows[n][i].ToString().Replace("'", "") + "','true')";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "datetime" ||
dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "date")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "null,'true')";
else
strSql = strSql + "'" + DateTime.Parse(dtTabela.Rows[n][i].ToString()) + "','true')";
}
else
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "0,'true')";
else
strSql = strSql + dtTabela.Rows[n][i].ToString() + ",'true')";
}
}
else
{
if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "boolean" ||
dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "logical")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'False',";
else
strSql = strSql + "'" + dtTabela.Rows[n][i].ToString() + "',";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "string")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'',";
else
strSql = strSql + "'" + dtTabela.Rows[n][i].ToString().Replace("'", "") + "',";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "byte")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'0',";
else
strSql = strSql + "'" + Encoding.ASCII.GetBytes(dtTabela.Rows[n][i].ToString()) + "',";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "character")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "'',";
else
strSql = strSql + "'" + dtTabela.Rows[n][i].ToString().Replace("'", "") + "',";
}
else if (dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "datetime" ||
dtColumn.Rows[i]["TYPE"].ToString().ToLower() == "date")
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "null,";
else
strSql = strSql + "'" + DateTime.Parse(dtTabela.Rows[n][i].ToString()) + "',";
}
else
{
if (string.IsNullOrWhiteSpace(dtTabela.Rows[n][i].ToString()))
strSql = strSql + "0,";
else
strSql = strSql + dtTabela.Rows[n][i].ToString() + ",";
}
}
}
try
{
SqlCommand dbCmd1 = new SqlCommand(strSql, dbCon);
dbCmd1.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine("Error " + ex.Message);
}
}
dbCon.Close();
dgvDados.DataSource = dtTabela;
}
}
|
Executando o projeto, para o arquivo DBF em questão iremos obter o seguinte resultado :
Verificando o banco de dados CadastroDB.mdf veremos a tabela contacts criada conforme mostrado abaixo:
Pegue o código do projeto aqui : WF_LeSalva_Dbf.zip
Salmos 18:2
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
https://www.c-sharpcorner.com/blogs/how-read-dbf-file-and-save-data-into-database-in-c-sharp
http://sailajareddy-technical.blogspot.com/2012/11/how-to-read-dbf-file-in-c-and-display.html
http://riteshkk2000.blogspot.com/2007/03/how-to-readwrite-data-from-dbf-file.html
NET - Lendo Arquivos DBF - Macoratti
Acessando arquivos DBF - Macoratti
C# - Importando dados de um arquivo DBF para um ... - Macoratti
Criando um arquivo DBF com ADO - Macoratti
Exportando para qualquer tipo de Banco de dados - Macoratti