Ho un metodo per leggere i dati dal file. Il problema è come gestire file troppo grandi per una semplice lettura e salvarli nel database? Stavo pensando di leggerne una parte e salvarla nel database, ma non so se avere un metodo asincrono con callback sia una buona idea.
Fondamentalmente penso che una classe di lettori non dovrebbe essere a conoscenza di alcuna interfaccia di database, quindi per poter notificare con successo una porzione di dati deve avere una callback. Non so se questo è un buon approccio o no.
private const int Buffer = 100000;
public Task ReadAsync(Action<Tuple<DataTable, int>> statusCallback) {
DataTable data;
return await Task.Run(() => {
var totalRows = GetRowsCount(); // iterates file to calculate total number of rows
var progress = 0;
if(totalRows < Buffer) {
/**Read whole file...*/
progress = 100;
}
else {
while(/**loop until end of file*/) {
for(var rowIndex = 0; rowIndex < Buffer; rowIndex++) {
var row = reader.Read();
/**Split, parse, etc...*/
data.Add(row);
}
progress += Buffer/totalRows * 100; // Add read rows to total result %
statusCallback(new Tuple(data, progress));
}
}
}
}
E poi salvalo
public void Start() {
_reader.ReadAsync(ReadingProgress);
}
private void ReadingProgress(DataTable data, int progress) {
_loadingBar.Update(progress);
using(var tran = _database.BeginTrans()) {
foreach(var row in data.Rows)
{
_database.Insert(row);
}
tran.Commit();
}
}
Per qualche ragione mi sembra sbagliato, ma non so perché. Qualche idea su come potrei migliorare questo?
EDIT: Vorrei informare gli utenti di quanto il programma legge del file, quindi ho bisogno di scorrere l'intero file una volta e leggere quante linee ha. Questo mi infastidisce, perché significa che devo ripetere un file due volte.
Un approccio a cui pensavo era ottenere la dimensione in byte della prima riga e quindi dividere la dimensione del file in base a quella dimensione. Mi darebbe un conteggio stimato delle linee in un file, ma non sono sicuro che l'errore di approssimazione non sarebbe troppo grande.