Repository navigation
Expand file tree
/
Copy pathProgram.cs
More file actions
77 lines (68 loc) · 3 KB
/
Copy pathProgram.cs
File metadata and controls
77 lines (68 loc) · 3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using InvoiceImporter.Application;
using InvoiceImporter.Domain;
using InvoiceImporter.Domain.Services;
using InvoiceImporter.Infrastructure;
namespace InvoiceImporter
{
/// <summary>
/// Composition root: reads the file path, wires the dependencies, and runs the import.
/// </summary>
sealed class Program
{
static async Task Main(string[] args)
{
using var loggerFactory = LoggerFactory.Create(builder =>
builder.AddSimpleConsole(o => o.SingleLine = true)
.SetMinimumLevel(LogLevel.Information));
var logger = loggerFactory.CreateLogger<Program>();
try
{
Console.Write("Enter the file path of the CSV file: ");
string? input = Console.ReadLine();
if (string.IsNullOrWhiteSpace(input))
{
throw new ArgumentException("No file path was entered.");
}
string filePath = NormalisePath(input);
using var dbContext = new InvoiceDbContext();
var csvReader = new CsvReader();
var repository = new InvoiceRepository(dbContext);
var dateTimeParser = new DateTimeParser();
var invoiceFactory = new InvoiceFactory(dateTimeParser);
var dataImporter = new DataImporter(
csvReader, loggerFactory.CreateLogger<DataImporter>(), repository, invoiceFactory);
// Ctrl+C cancels the import cleanly; nothing is saved unless SaveChanges completes.
using var cts = new CancellationTokenSource();
Console.CancelKeyPress += (_, e) =>
{
e.Cancel = true;
cts.Cancel();
};
await dataImporter.ImportData(filePath, cts.Token);
}
catch (OperationCanceledException)
{
logger.LogWarning("Import cancelled; nothing was saved");
Environment.ExitCode = 1;
}
catch (DbUpdateException ex) when (ex.InnerException is SqlException { Number: 2601 or 2627 })
{
// Unique index on InvoiceNumber: another run imported one of these invoices first.
logger.LogError(ex, "Invoice import failed: an invoice in the file has already been imported; nothing was saved");
Environment.ExitCode = 1;
}
catch (Exception ex)
{
logger.LogError(ex, "Invoice import failed");
Environment.ExitCode = 1;
}
}
// Only the surrounding quotes from Explorer's "Copy as path" need removing; the
// separators are already correct (doubling them breaks \\server\share paths).
internal static string NormalisePath(string input) =>
input.Trim().Trim('"');
}
}