/// <summary> /// constructor de la clase que implementa IImportService. /// /// se implemta este constructor para inyectar dependecias de otras clases. /// </summary> /// <param name="config">instancia de la clase que contiene la configuración general de la aplicación.</param> /// <param name="readFile">instancia de la clase IReadFileService que se inyecta en esta clase.</param> /// <param name="lineMap">instancia de la clase ILineMapperService que se inyecta en esta clase.</param> public ImportService(IOptions <Config> config, IReadFileService readFile, ILineMappingService lineMap, PruebaAAContext db, ISqlBulkImport bulkImport) { _config = config?.Value ?? throw new ArgumentNullException(nameof(config)); _readFile = readFile; _lineMap = lineMap; _bulkImport = bulkImport; _db = db; }
/// <summary> /// Vacia la tabla Stocks /// </summary> /// <returns></returns> private static async Task TruncateTable() { using (PruebaAAContext context = new PruebaAAContext()) { using (var connection = context.Database.GetDbConnection()) { await connection.OpenAsync(); using (var command = connection.CreateCommand()) { command.CommandText = "TRUNCATE TABLE Stocks"; var result = await command.ExecuteNonQueryAsync(); } } } }
public async Task InsertBulk(IEnumerable <StockEntity> stocks) { int recordCount = 50000; // Realice varias pruebas y 50000 me parecio una buena opcion para la insercion de records int skipCount = 0; int batchCount = 0; //var stopwatch = new Stopwatch(); while (skipCount <= stocks.Count()) { //stopwatch.Start(); // Insertamos por grupos para mejorar el rendimiento y no crashear la app var stockList = stocks.Skip(skipCount) .Take(recordCount) .Select(s => new StockEntity { Id = s.Id, Product = s.Product, Date = s.Date, PointOfSale = s.PointOfSale, Stock = s.Stock }); await _context.Stocks.AddRangeAsync(stockList); await _context.SaveChangesAsync(); skipCount += recordCount; //stopwatch.Stop(); //Console.WriteLine("Tiempo de ejecucion: " + stopwatch.Elapsed.TotalSeconds); //stopwatch.Restart(); batchCount++; // Dispose el context para limpiar las miles de entidades atadas a el if (batchCount >= 10) { _context.Dispose(); _context = new PruebaAAContext(); batchCount = 0; } } }
/// <summary> /// Lee cada una de las lineas del archivo, separa los campos del fichero CSV, crea el modelo y lo almacena en BD /// </summary> /// <param name="fileName"></param> /// <returns></returns> private static void ProcessCSVFile(string fileName) { //Verificar si existe el fichero if (!File.Exists(fileName)) { Console.WriteLine("No existe el fichero CSV."); return; } Console.WriteLine("Procesando fichero CSV."); try { //Determinar la cantidad de tiempo para procesar el archivo Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); var lineCount = File.ReadAllLines(fileName).Length; Console.WriteLine("Total de lineas {0}.", lineCount); //Se crea el TextFieldParser para leer cada linea del fichero CSV using (TextFieldParser parser = new TextFieldParser(fileName)) { parser.TextFieldType = FieldType.Delimited; parser.SetDelimiters(";"); parser.ReadLine(); //Descartar la primera linea PruebaAAContext context = new PruebaAAContext(); //Se vacia la tabla con data anterior TruncateTable().Wait(); Console.WriteLine("Leyendo fichero y guardando registros..."); int batchSize = 100; //Define la cantidad de lineas a procesar para guardar en BD int i = 0; List <Stock> list = new List <Stock>(); //while (i < 10000) while (!parser.EndOfData) { int percent = (int)Math.Round((double)(100 * i) / lineCount); Console.Write("\rLinea {0} - {1} %", i + 1, percent); if (i != 0 && i % batchSize == 0) //Cada vez que se llega al tamaño del lineas a procesar se guardan los cambios y se crea un nuevo DBContext { context.Stocks.AddRange(list); context.SaveChanges(); context = new PruebaAAContext(); context.ChangeTracker.DetectChanges(); list.Clear(); } //Se lee una linea de fichero string[] fields = parser.ReadFields(); if (fields != null && fields.Length == 4) { //Se crea el modelo con los campos de la linea Stock stock = new Stock { PointOfSale = fields[0], Product = fields[1], Date = fields[2], //DateTime.ParseExact(fields[2], "yyyy-MM-dd", CultureInfo.InvariantCulture), StockQty = int.Parse(fields[3]) }; //Se agrega a la lista que va al AddRange list.Add(stock); } i++; } context.Stocks.AddRange(list); context.ChangeTracker.DetectChanges(); context.SaveChanges(); list.Clear(); } stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Console.WriteLine(); Console.WriteLine("Fichero completado."); string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine("Tiempo total: " + elapsedTime); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
/// <summary> /// constructor de la clase. /// /// se inyecta una instancia del contexto de datos. /// </summary> /// <param name="db"></param> public CreateTable(PruebaAAContext db) { _db = db; }
public SqlBulkImport(PruebaAAContext db) { _db = db; }
public StockRepository() { _context = new PruebaAAContext(); }