AppDbContext: Add ExecuteBatch() and ExecuteScalar()

This commit is contained in:
2024-01-05 13:41:27 +01:00
parent f28a1a2db9
commit 121ca10261
4 changed files with 67 additions and 110 deletions

View File

@ -100,6 +100,18 @@ namespace Elwig.Helpers {
return cnx;
}
public static async Task ExecuteBatch(SqliteConnection cnx, string sql) {
using var cmd = cnx.CreateCommand();
cmd.CommandText = sql;
await (await cmd.ExecuteReaderAsync()).CloseAsync();
}
public static async Task<object?> ExecuteScalar(SqliteConnection cnx, string sql) {
using var cmd = cnx.CreateCommand();
cmd.CommandText = sql;
return await cmd.ExecuteScalarAsync();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlite(ConnectionString);
optionsBuilder.UseLazyLoadingProxies();

View File

@ -13,25 +13,13 @@ namespace Elwig.Helpers {
private static int VersionOffset = 0;
private static async Task ExNonQuery(SqliteConnection cnx, string sql) {
using var cmd = cnx.CreateCommand();
cmd.CommandText = sql;
await (await cmd.ExecuteReaderAsync()).CloseAsync();
}
private static async Task<object?> ExScalar(SqliteConnection cnx, string sql) {
using var cmd = cnx.CreateCommand();
cmd.CommandText = sql;
return await cmd.ExecuteScalarAsync();
}
public static async Task<string> CheckDb() {
using var cnx = AppDbContext.Connect();
var applId = (long?)await ExScalar(cnx, "PRAGMA application_id") ?? 0;
var applId = (long?)await AppDbContext.ExecuteScalar(cnx, "PRAGMA application_id") ?? 0;
if (applId != 0x454C5747) throw new Exception("Invalid application_id of database");
var schemaVers = (long?)await ExScalar(cnx, "PRAGMA schema_version") ?? 0;
var schemaVers = (long?)await AppDbContext.ExecuteScalar(cnx, "PRAGMA schema_version") ?? 0;
VersionOffset = (int)(schemaVers % 100);
if (VersionOffset != 0) {
// schema was modified manually/externally
@ -39,7 +27,7 @@ namespace Elwig.Helpers {
}
await UpdateDbSchema(cnx, (int)(schemaVers / 100), RequiredSchemaVersion);
var userVers = (long?)await ExScalar(cnx, "PRAGMA user_version") ?? 0;
var userVers = (long?)await AppDbContext.ExecuteScalar(cnx, "PRAGMA user_version") ?? 0;
var major = userVers >> 24;
var minor = (userVers >> 16) & 0xFF;
var patch = userVers & 0xFFFF;
@ -48,7 +36,7 @@ namespace Elwig.Helpers {
(App.VersionMajor == major && App.VersionMinor > minor) ||
(App.VersionMajor == major && App.VersionMinor == minor && App.VersionPatch > patch)) {
long vers = (App.VersionMajor << 24) | (App.VersionMinor << 16) | App.VersionPatch;
await ExNonQuery(cnx, $"PRAGMA user_version = {vers}");
await AppDbContext.ExecuteBatch(cnx, $"PRAGMA user_version = {vers}");
}
return $"{major}.{minor}.{patch}";
@ -83,7 +71,7 @@ namespace Elwig.Helpers {
if (toExecute.Count == 0)
return;
await ExNonQuery(cnx, """
await AppDbContext.ExecuteBatch(cnx, """
PRAGMA locking_mode = EXCLUSIVE;
PRAGMA foreign_keys = OFF;
BEGIN EXCLUSIVE;
@ -91,9 +79,9 @@ namespace Elwig.Helpers {
foreach (var script in toExecute) {
using var stream = asm.GetManifestResourceStream(script) ?? throw new Exception("Unable to load embedded resource");
using var reader = new StreamReader(stream);
await ExNonQuery(cnx, await reader.ReadToEndAsync());
await AppDbContext.ExecuteBatch(cnx, await reader.ReadToEndAsync());
}
await ExNonQuery(cnx, $"""
await AppDbContext.ExecuteBatch(cnx, $"""
PRAGMA foreign_key_check;
COMMIT;
PRAGMA foreign_keys = ON;

View File

@ -22,19 +22,13 @@ namespace Elwig.Helpers.Billing {
public async Task FinishSeason() {
using var cnx = await AppDbContext.ConnectAsync();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
UPDATE season
SET (start_date, end_date) = (SELECT MIN(date), MAX(date) FROM delivery WHERE year = {Year})
WHERE year = {Year}
""";
await cmd.ExecuteNonQueryAsync();
}
WHERE year = {Year};
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"DELETE FROM delivery_part_bucket WHERE year = {Year}";
await cmd.ExecuteNonQueryAsync();
}
DELETE FROM delivery_part_bucket WHERE year = {Year};
""");
}
public async Task CalculateBuckets(bool allowAttrsIntoLower, bool avoidUnderDeliveries, bool honorGebunden) {
@ -108,15 +102,12 @@ namespace Elwig.Helpers.Billing {
lastMgNr = mgnr;
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
INSERT INTO delivery_part_bucket (year, did, dpnr, bktnr, discr, value)
VALUES {string.Join(",\n ", inserts.Select(i => $"({Year}, {i.Item1}, {i.Item2}, {i.Item3}, '{i.Item4}', {i.Item5})"))}
ON CONFLICT DO UPDATE
SET discr = excluded.discr, value = value + excluded.value
""";
await cmd.ExecuteNonQueryAsync();
}
SET discr = excluded.discr, value = value + excluded.value;
""");
if (!avoidUnderDeliveries)
return;
@ -186,25 +177,17 @@ namespace Elwig.Helpers.Billing {
if (needed == 0) break;
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
INSERT INTO delivery_part_bucket (year, did, dpnr, bktnr, discr, value)
VALUES {string.Join(",\n ", posChanges.Select(i => $"({Year}, {i.Item1}, {i.Item2}, {i.Item3}, '', {i.Item4})"))}
ON CONFLICT DO UPDATE
SET value = value + excluded.value
""";
await cmd.ExecuteNonQueryAsync();
}
SET value = value + excluded.value;
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
INSERT INTO delivery_part_bucket (year, did, dpnr, bktnr, discr, value)
VALUES {string.Join(",\n ", negChanges.Select(i => $"({Year}, {i.Item1}, {i.Item2}, {i.Item3}, '', {i.Item4})"))}
ON CONFLICT DO UPDATE
SET value = excluded.value
""";
await cmd.ExecuteNonQueryAsync();
}
SET value = excluded.value;
""");
}
}
}

View File

@ -22,8 +22,7 @@ namespace Elwig.Helpers.Billing {
public async Task Commit() {
await Revert();
using var cnx = await AppDbContext.ConnectAsync();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
INSERT INTO credit (year, tgnr, mgnr, avnr, net_amount, prev_net_amount, vat, modifiers, prev_modifiers)
SELECT s.year,
COALESCE(t.tgnr, 0) + ROW_NUMBER() OVER(ORDER BY m.mgnr) AS tgnr,
@ -55,53 +54,35 @@ namespace Elwig.Helpers.Billing {
FROM v_under_delivery u
JOIN area_commitment_type t ON t.vtrgid = u.bucket
GROUP BY year, mgnr) u ON (u.year, u.mgnr) = (s.year, m.mgnr)
WHERE s.year = {Year} AND v.avnr = {AvNr}
""";
await cmd.ExecuteNonQueryAsync();
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"UPDATE payment_variant SET test_variant = FALSE WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
WHERE s.year = {Year} AND v.avnr = {AvNr};
UPDATE payment_variant SET test_variant = FALSE WHERE (year, avnr) = ({Year}, {AvNr});
""");
}
public async Task Revert() {
using var cnx = await AppDbContext.ConnectAsync();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"DELETE FROM credit WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"UPDATE payment_variant SET test_variant = TRUE WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
await AppDbContext.ExecuteBatch(cnx, $"""
DELETE FROM credit WHERE (year, avnr) = ({Year}, {AvNr});
UPDATE payment_variant SET test_variant = TRUE WHERE (year, avnr) = ({Year}, {AvNr});
""");
}
protected async Task SetCalcTime() {
using var cnx = await AppDbContext.ConnectAsync();
using var cmd = cnx.CreateCommand();
cmd.CommandText = $"UPDATE payment_variant SET calc_time = UNIXEPOCH() WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
await AppDbContext.ExecuteBatch(cnx, $"""
UPDATE payment_variant SET calc_time = UNIXEPOCH() WHERE (year, avnr) = ({Year}, {AvNr})
""");
}
protected async Task DeleteInDb() {
using var cnx = await AppDbContext.ConnectAsync();
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"DELETE FROM payment_delivery_part_bucket WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"DELETE FROM payment_delivery_part WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"DELETE FROM payment_member WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"UPDATE payment_variant SET calc_time = NULL WHERE (year, avnr) = ({Year}, {AvNr})";
await cmd.ExecuteNonQueryAsync();
}
await AppDbContext.ExecuteBatch(cnx, $"""
DELETE FROM payment_delivery_part_bucket WHERE (year, avnr) = ({Year}, {AvNr});
DELETE FROM payment_delivery_part WHERE (year, avnr) = ({Year}, {AvNr});
DELETE FROM payment_member WHERE (year, avnr) = ({Year}, {AvNr});
UPDATE payment_variant SET calc_time = NULL WHERE (year, avnr) = ({Year}, {AvNr});
""");
}
protected async Task CalculateMemberModifiers() {
@ -110,8 +91,7 @@ namespace Elwig.Helpers.Billing {
var lastYears = 3;
var multiplier = 0.50;
var modName = "Treue%";
using var cmd = cnx.CreateCommand();
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
INSERT INTO payment_member (year, avnr, mgnr, net_amount, mod_abs, mod_rel)
SELECT c.year, {AvNr}, s.mgnr, 0,
ROUND(s.sum * COALESCE(m.abs, 0)),
@ -129,8 +109,7 @@ namespace Elwig.Helpers.Billing {
ON CONFLICT DO UPDATE
SET mod_abs = mod_abs + excluded.mod_abs,
mod_rel = mod_rel + excluded.mod_rel
""";
await cmd.ExecuteNonQueryAsync();
""");
}
}
@ -164,19 +143,15 @@ namespace Elwig.Helpers.Billing {
inserts.Add((part.Year, part.DId, part.DPNr, part.BktNr, priceL, amount));
}
using (var cmd = cnx.CreateCommand()) {
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
INSERT INTO payment_delivery_part_bucket (year, did, dpnr, bktnr, avnr, price, amount)
VALUES {string.Join(",\n ", inserts.Select(i => $"({i.Year}, {i.DId}, {i.DPNr}, {i.BktNr}, {AvNr}, {i.Price}, {i.Amount})"))}
""";
await cmd.ExecuteNonQueryAsync();
}
VALUES {string.Join(",\n ", inserts.Select(i => $"({i.Year}, {i.DId}, {i.DPNr}, {i.BktNr}, {AvNr}, {i.Price}, {i.Amount})"))};
""");
}
protected async Task CalculateModifiers() {
using var cnx = await AppDbContext.ConnectAsync();
using var cmd = cnx.CreateCommand();
cmd.CommandText = $"""
await AppDbContext.ExecuteBatch(cnx, $"""
INSERT INTO payment_delivery_part (year, did, dpnr, avnr, net_amount, mod_abs, mod_rel)
SELECT d.year, d.did, d.dpnr, {AvNr}, 0, COALESCE(m.abs, 0), COALESCE(m.rel, 0)
FROM delivery_part d
@ -186,8 +161,7 @@ namespace Elwig.Helpers.Billing {
ON CONFLICT DO UPDATE
SET mod_abs = mod_abs + excluded.mod_abs,
mod_rel = mod_rel + excluded.mod_rel
""";
await cmd.ExecuteNonQueryAsync();
""");
}
}
}