6
I’ve been making a data import for a project on ASP.NET MVC 5 with EF 6.1 and SQL Server 2008 where the import data source was a file txt.
The record lines of the file were not very large but contained a certain amount of information to process. As for example, in the record line there was the data of an employee, a position in the company, neighborhood, city etc. Everything becoming a table in my model.
So, line by line I checked the existence of each neighborhood, city, position and all other data to obtain the identification of those who were already registered or then record the non-existent yet.
Later I opted to cache. I simply uploaded the data in generic lists to the memory and before going into the database I checked that information in memory.
The other information did not generate a large number of data, but the register of employees did. There were more than 27 thousand records.
Anyway, my question is about a performance problem I had while making the import using the EPH. After the first thousand records (a little more) the import performance drops a lot, registering one employee every 1 or 2 seconds.
Until I realized that by canceling the import process and starting again the first thousand records were imported in a good time, but after the thousand records the thing went back slowly.
I resolved destroying my context every thousand records and creating again. Then the import had a good performance from start to finish.
I’d like to know that you’ve been through something similar, why does this occur? It may be some Entity Framework configuration? Mine is out of settings.
Follow the import code snippet for anyone who wants to analyze:
private List<Domain.int> Matriculas;
private List<Domain.CentroCusto> CacheCentrosCusto;
private List<Domain.Local> CacheLocais;
private List<Domain.Profissao> CacheProfissoes;
private List<Domain.Cidade> CacheCidades;
private List<Domain.Bairro> CacheBairros;
//Funcionarios
public ActionResult Funcionarios(string filePath)
{
var fileInfo = new FileInfo(filePath);
if (!file.Exists)
throw new Exception("Arquivo não encontrado");
Matriculas = contexto.Funcionarios
.Select(x => x.Matricula)
.ToList();
CacheCentrosCusto = contexto.CentrosCusto.ToList();
CacheLocais = contexto.Locais.ToList();
CacheProfissoes = contexto.Profissoes.ToList();
CacheCidades = contexto.Cidades.ToList();
CacheBairros = contexto.Bairros.ToList();
var file = new System.IO.StreamReader(filePath);
try
{
var count = 0;
string line = "";
while ((line = file.ReadLine()) != null)
{
string[] campos = line.Split(';');
int matricula;
if (int.TryParse(campos[0].Trim(), out matricula))
{
if (Matriculas.Contains(matricula))
continue;
}
var funcionario = new Domain.Funcionario();
funcionario.Matricula = matricula;
// obtendo outros dados ...
funcionario.CentroCustoId = GetCentroCustoId(campos[34].Trim());
funcionario.LocalId = GetLocalId(campos[35].Trim());
funcionario.ProfissaoId = GetProfissaoId(campos[36].Trim());
//Cidade e Bairro
funcionario.BairroId = null;
var bai_desc = campos[11].Trim();
if (!string.IsNullOrEmpty(bai_desc))
{
var cid_uf = "";
var cid_desc = campos[12].Trim();
// trabalho a string ...
var cidade = new Domain.Cidade();
cidade.Nome = cid_desc;
cidade.Uf = cid_uf;
var bairro = new Domain.Bairro();
bairro.Nome = bai_desc;
funcionario.BairroId = GetBairroId(bairro, cidade);
}
try
{
contexto.Funcionarios.Add(funcionario);
contexto.SaveChanges();
Matriculas.Add(matricula);
count++;
if (count == 1000)
{
count = 0;
contexto.Dispose();
contexto = new DataAccess.Context();
}
}
catch (DbEntityValidationException e) { ... }
catch (Exception e) { ... }
}
}
finally
{
file.Close();
}
return RedirectToAction("Index");
}
My context is created in the Controller class constructor and destroyed in the method Dispose
.
Notice that there is a counter and every thousand records I destroy and create again my context.
An example for the other methods present:
OBS: All other methods contained in the import code have the same structure as this.
private int? GetProfissaoId(string descricao)
{
int? profissao_id = null;
if (!string.IsNullOrEmpty(descricao))
{
var profissaoTemp = CacheProfissoes
.SingleOrDefault(x => x.Descricao.ToLower().Trim() == descricao.ToLower().Trim());
if (profissaoTemp == null)
{
try
{
contexto.Profissoes.Add(profissao);
contexto.SaveChanges();
CacheProfissoes.Add(profissao);
profissao_id = profissao.Id;
}
catch (DbEntityValidationException e) { ... }
catch (Exception e) { ... }
profissao_id = profissao.Id;
}
else
{
profissao_id = profissaoTemp.Id;
}
}
return profissao_id;
}
Could you put an excerpt of this code? how does Savechanges do?
– user6026
I have some things that I would change in this little code! the hard one is to test
– user6026