Skip to content

Instantly share code, notes, and snippets.

@panicoenlaxbox
Last active September 12, 2019 19:32
Show Gist options
  • Save panicoenlaxbox/2324429c276ff48ebfd90c00f7604017 to your computer and use it in GitHub Desktop.
Save panicoenlaxbox/2324429c276ff48ebfd90c00f7604017 to your computer and use it in GitHub Desktop.
Download file and blob in wrong and right way
//<Project Sdk="Microsoft.NET.Sdk">
// <PropertyGroup>
// <OutputType>Exe</OutputType>
// <TargetFramework>netcoreapp2.2</TargetFramework>
// </PropertyGroup>
// <ItemGroup>
// <PackageReference Include="CsvHelper" Version="12.1.2" />
// <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="2.2.6" />
// <PackageReference Include="TinyCsvParser" Version="2.5.2" />
// <PackageReference Include="WindowsAzure.Storage" Version="9.3.3" />
// <PackageReference Include="EFCore.BulkExtensions" Version="2.6.0" />
// </ItemGroup>
//</Project>
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using CsvHelper;
using CsvHelper.Configuration;
using EFCore.BulkExtensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Auth;
using Microsoft.WindowsAzure.Storage.Blob;
using TinyCsvParser;
using TinyCsvParser.Mapping;
using TinyCsvParser.TypeConverter;
namespace ConsoleApp3
{
class Program
{
private static SyncContext CreateSyncContext()
{
var options = new DbContextOptionsBuilder<SyncContext>()
.UseSqlServer(@"Server=.;Database=Sync;Trusted_Connection=True;")
.Options;
return new SyncContext(options);
}
static async Task Main(string[] args)
{
//var url = "h";
const string sasToken = "";
const string accountName = "";
const string containerName = "";
const string blobName = "";
//await HttpGetForLargeFileInWrongWay(url);
//await HttpGetForLargeFileInRightWay(url);
//await GetBlobInWrongWay(sasToken, accountName, containerName, blobName);
await GetBlobInRightWay(sasToken, accountName, containerName, blobName);
}
private static async Task HttpGetForLargeFileInWrongWay(string url)
{
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url))
using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
{
string fileToWriteTo = Path.GetTempFileName();
Console.WriteLine(fileToWriteTo);
using (Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create))
{
await streamToReadFrom.CopyToAsync(streamToWriteTo);
}
}
}
}
private static async Task HttpGetForLargeFileInRightWay(string url)
{
// http://www.tugberkugurlu.com/archive/efficiently-streaming-large-http-responses-with-httpclient
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
{
string fileToWriteTo = Path.GetTempFileName();
Console.WriteLine(fileToWriteTo);
using (Stream streamToWriteTo = File.Open(fileToWriteTo, FileMode.Create))
{
await streamToReadFrom.CopyToAsync(streamToWriteTo);
}
}
}
}
private static async Task GetBlobInWrongWay(string sasToken, string accountName, string containerName, string blobName)
{
StorageCredentials credentials = new StorageCredentials(sasToken);
CloudStorageAccount account = new CloudStorageAccount(credentials, accountName, endpointSuffix: null, useHttps: true);
CloudBlobClient client = account.CreateCloudBlobClient();
CloudBlobContainer container = client.GetContainerReference(containerName);
CloudBlob blob = container.GetBlobReference(blobName);
using (var stream = new MemoryStream())
{
await blob.DownloadToStreamAsync(stream);
IEnumerable<SyncBiDailyStock> entities = GetCsvInWrongWay(stream);
Console.WriteLine(entities.Count());
}
}
public static async Task GetBlobInRightWay(string sasToken, string accountName, string containerName, string blobName)
{
StorageCredentials credentials = new StorageCredentials(sasToken);
CloudStorageAccount account =
new CloudStorageAccount(credentials, accountName, endpointSuffix: null, useHttps: true);
CloudBlobClient client = account.CreateCloudBlobClient();
CloudBlobContainer container = client.GetContainerReference(containerName);
CloudBlob blob = container.GetBlobReference(blobName);
var blockNumberOf = 1;
Stopwatch sw;
using (var context = CreateSyncContext())
{
await context.Database.EnsureDeletedAsync();
await context.Database.EnsureCreatedAsync();
sw = Stopwatch.StartNew();
using (var stream = await blob.OpenReadAsync())
{
using (StreamReader reader = new StreamReader(stream))
{
var header = await reader.ReadLineAsync();
var eof = false;
do
{
var sw2 = Stopwatch.StartNew();
var block = new StringBuilder();
block.AppendLine(header);
var rowNumberOf = 0;
const int blockSize = 50000;
while (rowNumberOf < blockSize)
{
var line = await reader.ReadLineAsync();
if (line == null)
{
eof = true;
break;
}
block.AppendLine(line);
rowNumberOf++;
}
using (var csvReader = new StringReader(block.ToString()))
{
var items = GetCsvInRightWayWithCvsHelper(csvReader);
await context.BulkInsertAsync(items);
Console.WriteLine($"Block number {blockNumberOf} - {items.Count} rows - {sw2.Elapsed:g} elapsed time");
blockNumberOf++;
}
//using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(block.ToString())))
//{
// var items = GetCsvInRightWayWithTinyCsvParser(memoryStream);
// await context.BulkInsertAsync(items);
// Console.WriteLine($"Block number {blockNumberOf} - {items.Count} rows - {sw2.Elapsed:g} elapsed time");
// blockNumberOf++;
//}
} while (!eof);
}
}
}
Console.WriteLine(sw.Elapsed.ToString("g"));
}
public static IList<SyncBiDailyStock> GetCsvInRightWayWithCvsHelper(TextReader textReader)
{
using (var csvReader = new CsvReader(textReader))
{
csvReader.Configuration.RegisterClassMap<SyncBiDailyStockMap>();
csvReader.Configuration.HasHeaderRecord = true;
csvReader.Configuration.Delimiter = ";";
return csvReader.GetRecords<SyncBiDailyStock>().ToList();
}
}
public static IList<SyncBiDailyStock> GetCsvInRightWayWithTinyCsvParser(Stream stream)
{
CsvParserOptions csvParserOptions = new CsvParserOptions(true, ';');
SyncBiDailyStockMapping csvMapper = new SyncBiDailyStockMapping();
CsvParser<SyncBiDailyStock> csvParser = new CsvParser<SyncBiDailyStock>(csvParserOptions, csvMapper);
return csvParser.ReadFromStream(stream, Encoding.UTF8).Select(r => r.Result).ToList();
}
public static IEnumerable<SyncBiDailyStock> GetCsvInWrongWay(Stream csvStream)
{
csvStream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(csvStream))
using (var csv = new CsvReader(reader))
{
csv.Configuration.RegisterClassMap<SyncBiDailyStockMap>();
csv.Configuration.HasHeaderRecord = true;
csv.Configuration.Delimiter = ";";
return csv.GetRecords<SyncBiDailyStock>().ToList();
}
}
}
public class SyncBiDailyStock
{
public int Id { get; set; }
public string PointOfSale { get; set; }
public string ProductCode { get; set; }
public DateTime Date { get; set; }
public int DailyStock { get; set; }
}
// CsvHelper
public class SyncBiDailyStockMap : ClassMap<SyncBiDailyStock>
{
public SyncBiDailyStockMap()
{
Map(m => m.PointOfSale).Index(1).Name("PointOfSale");
Map(m => m.ProductCode).Index(0).Name("Product");
Map(m => m.Date).TypeConverterOption.Format("yyyy-MM-dd").Index(2).Name("Date");
Map(m => m.DailyStock).Index(3).Name("Stock");
}
}
//TinyCsvParser
public class SyncBiDailyStockMapping : CsvMapping<SyncBiDailyStock>
{
public SyncBiDailyStockMapping()
{
MapProperty(0, m => m.PointOfSale);
MapProperty(1, m => m.ProductCode);
MapProperty(2, m => m.Date, new DateTimeConverter("yyyy-MM-dd"));
MapProperty(3, m => m.DailyStock);
}
}
public class SyncContext : DbContext
{
public SyncContext(DbContextOptions<SyncContext> options) : base(options)
{
}
public DbSet<SyncBiDailyStock> SyncBiDailyStocks { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment