Visão Geral
Neste tópico iremos explorar um cenário de importação de arquivo CSV, considerando a existência das seguintes tabelas:
archives:
-- PostgreSQL
CREATE TABLE samples.archives
(
id VARCHAR (255) NOT NULL,
name VARCHAR(255),
size INT,
blob BYTEA,
hash VARCHAR(40)
);
ALTER TABLE Arquivo ADD CONSTRAINT pk_archives_id PRIMARY KEY (Id);
products:
-- PostgreSQL
CREATE TABLE samples.products
(
id serial NOT NULL,
name text NOT NULL,
price numeric(12, 2) NOT NULL,
unit integer NOT NULL,
CONSTRAINT pk_products_id PRIMARY KEY (id)
);
para esse exemplo também será criado uma função no banco para efetuar a gravação na tabela:
CREATE FUNCTION samples.product_add(IN name_arg text, IN price_arg text, IN unit_arg text)
RETURNS void
LANGUAGE 'sql'
AS $BODY$
insert into samples.products (name, price, unit)
values (name_arg, price_arg::decimal, unit_arg::integer);
$BODY$;
COMMENT ON FUNCTION samples.product_add(text, numeric, integer)
IS 'Adiciona um produto na tabela products';
E um arquivo csv no seguinte formato (Sem a linha contendo o nome das colunas) “name;price;unit”.
Iremos criar um formulário que irá usar um código c# para efetuar a leitura do csv e efetuar a gravação na tabela products. Nesse formulário conterá os seguintes componentes:
- Variáveis:
- guid
- Procedimentos:
- btnImport_Click
- Form_Load
- uplFile_FileUploaded
- Campos:
- txtSeparator
- uplFile
- btnImport
Lendo CSV
No procedimento btnImport_Click iremos adicionar um comando para executar um código c#. Nele iremos adicionar o seguinte código:
using LATROMI.Extensions;
using System.Collections.Generic;
using System.IO;
void Insert(List<string[]> columnsData)
{
using (var connection = Database.CreateConnection("LATROMI"))
{
connection.Open();
foreach (var data in columnsData)
{
connection.ExecuteNonQuery(
"select samples.product_add(@name, @price, @unit)",
new Dictionary<string, object>() {
["@name"] = data[0],
["@price"] = data[1].Replace(',', '.'),
["@unit"] = data[2]
}
);
}
}
}
byte[] GetFileFromDB(string id)
{
using (var connection = Database.CreateConnection("LATROMI"))
{
connection.Open();
using (var reader = connection.ExecuteReader(
string.Concat("SELECT blob FROM samples.archives WHERE id = '", id, "'")
))
{
if (reader.Read())
return (byte[])reader["blob"];
}
}
return null;
}
List<string[]> ReadCsv(Stream data, char separator = ';')
{
List<string[]> columns = new List<string[]>();
using (var sr = new StreamReader(data))
{
while (!sr.EndOfStream)
{
string line = sr.ReadLine() ?? string.Empty;
if (string.IsNullOrEmpty(line))
continue;
string[] columnSplited = line.Split(separator);
if (columns.Count > 0 && columns.Last().Length != columnSplited.Length)
throw new FormatException(string.Format("The values split on line {0} are different from the other lines already read.", columns.Count + 1));
columns.Add(columnSplited);
}
}
return columns;
}
byte[] file = GetFileFromDB((string)Variables["guid"].Value);
char separator = Fields["txtSeparator"].Value.ToString()[0];
List<string[]> fileData = ReadCsv(new MemoryStream(file), separator);
Insert(fileData);
Criação do Formulário
Campos
-
txtSeparator:
Campo do tipo “TextBox”, que será responsável por indicar qual o tipo de separador do arquivo csv.
Configuração do campo →
-
uplFile
Campo do tipo “Upload”, que receberá o arquivo para importação.
Configuração do campo →
Eventos →
-
btnImport
Campo do tipo “Button”, que irá efetuar o submit do arquivo.
Configuração do campo →
Eventos →
Procedimentos
- Form_Load:
Procedimento vinculado no evento de Load do formulário, que irá popular a variável “guid” com o seguinte código c#:
return Guid.NewGuid();
-
uplFile_FileUploaded:
Procedimento vinculado ao evento de FileUploaded do campo Upload, que será responsável por atualizar a variável “guid” para um novo valor usando mesmo código c# apresentado anteriormente, no populate. -
btnImport_Click:
Procedimento responsável, por importar o arquivo csv para a tabela products usando o código apresentado na sessão Lendo CSV:
Conclusão
Ao efetuar todos os passos acima você terá o seguinte resultado:
-
Formulário de importação:
-
Consulta da tabela products: