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; 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) { protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
optionsBuilder.UseSqlite(ConnectionString); optionsBuilder.UseSqlite(ConnectionString);
optionsBuilder.UseLazyLoadingProxies(); optionsBuilder.UseLazyLoadingProxies();

View File

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

View File

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

View File

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