Test funzione di lettura dal DB: GetRacById(IDrac)
Test degli spunti ottenuti da una chat con Gemini. - [X] Test della classe cRac.cs - [ ] Test della funzione di salvataggio sul DB - [X] Test della funzione di lettura dal DB - [ ] Test della funzione di ricerca nel DB - [ ] Test funzione di cancellazione nel DB - [ ] Test nella ricerca di duplicati - [X] Test della funzione di esportazione in html con stile Riepilogo della chat: - connesso a gemini con chrome e utente mirko - dato in pasto il file *ATDB Database Schema.sql* con la struttura del DB - richiesto la classe cRac per rappresentare un racconto. - ottenuto *cRac.cs* - richiesto come salvare un cRac sul DB con diagnostica errori ed evitando spurie sul DB - ottenuto *Salvataggio cRac su DB.cs* - richiesto come leggere un racconto - ottenuto *GetRaccontoById.cs* - richiesto: ragruppiamo le funzioni di helper su un file Helper.cs e quelle di lettura/scrittura sul DB sul file DB.cs - ottenuto *Helper.cs* e *DB.cs* - richiesto: facciamo le ricerche avanzate per titolo, tag, autore, data di creazione, sorgente - ottenuta la nuova versione di *Aggiornamento 1 di DB.cs* - richiesto come eliminare un racconto dal DB - ottenuta la nuova versione di *Aggiornamento 2 di DB.cs* - richiesto: come ricercare racconti duplicati - ottenuto spunti di ricerca salvati in *Ricerca duplicati.cs* - richiesto come fare il merge di racconti duplicati - ottenuto *merge.cs* - richiesto delle idee per la UI - ottenuto il file *UI_idee.md* - richiesto un esempio di esportazione di un racconto in html con stile - ottenuto: *export.cs*
This commit is contained in:
1 parent
8fbe7866bf
commit
56920d059d
3 files changed
+155
-19
No files matched your search
+111
-1
@@ -867,7 +867,7 @@ namespace A69WD {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="IDrac">Identificativo del racconto desiderato</param>
|
/// <param name="IDrac">Identificativo del racconto desiderato</param>
|
||||||
/// <returns>Ritorna il racconto estratto dal DB</returns>
|
/// <returns>Ritorna il racconto estratto dal DB</returns>
|
||||||
public cRac GetRacById(long IDrac) {
|
public cRac GetRacById_Orig(long IDrac) {
|
||||||
lock (objLock) {
|
lock (objLock) {
|
||||||
cRac rac = null;
|
cRac rac = null;
|
||||||
List<string> tmp = null;
|
List<string> tmp = null;
|
||||||
@@ -1071,8 +1071,105 @@ namespace A69WD {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public cRac GetRacById(long IDrac) {
|
||||||
|
/*
|
||||||
|
* Il metodo più pulito e leggibile consiste nell'eseguire una query principale per
|
||||||
|
* i dati del racconto e poi delle query mirate per popolare le collezioni.
|
||||||
|
*
|
||||||
|
* Ecco come implementare la funzione in C# utilizzando Microsoft.Data.Sqlite.
|
||||||
|
*
|
||||||
|
* Spiegazione della logica:
|
||||||
|
* - LEFT JOIN: Ho usato i LEFT JOIN nella query principale così, anche se un racconto
|
||||||
|
* non ha ancora una trama o un voto assegnato, il record viene comunque recuperato
|
||||||
|
* correttamente senza errori.
|
||||||
|
* - Mapping Manuale: Poiché non stiamo usando un ORM pesante (come Entity Framework),
|
||||||
|
* mappiamo manualmente le colonne del reader alle proprietà dell'oggetto cRac.
|
||||||
|
* - Gestione Valori Nulli: Noterai il controllo reader["Trama"]?.ToString() ?? "" che
|
||||||
|
* evita eccezioni nel caso in cui certi campi opzionali siano vuoti nel database.
|
||||||
|
* - Helper GetList: Per evitare di riscrivere lo stesso codice 3 volte per Autori,
|
||||||
|
* Tags e Origini, ho creato una piccola funzione di supporto.
|
||||||
|
*
|
||||||
|
* Questo approccio è molto performante su SQLite e ti restituisce l'oggetto cRac
|
||||||
|
* esattamente come lo avevi immaginato, pronto per essere mostrato nella tua
|
||||||
|
* interfaccia utente.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
lock (objLock) {
|
||||||
|
cRac rac = null;
|
||||||
|
|
||||||
|
// 1. Query principale: Dati Racconto, Trama e Voto
|
||||||
|
string queryBase = @"
|
||||||
|
SELECT r.*, t.Trama, v.Voto as Voto
|
||||||
|
FROM Racconti r
|
||||||
|
LEFT JOIN Trame t ON r.IDrac = t.IDrac
|
||||||
|
LEFT JOIN Links_Rac_Vot lrv ON r.IDrac = lrv.IDrac
|
||||||
|
LEFT JOIN Voti v ON lrv.IDvot = v.IDvot
|
||||||
|
WHERE r.IDrac = @IDrac";
|
||||||
|
using (SQLiteCommand cmd = new SQLiteCommand(queryBase, cn)) {
|
||||||
|
cmd.Parameters.AddWithValue("@IDrac", IDrac);
|
||||||
|
using (SQLiteDataReader reader = cmd.ExecuteReader()) {
|
||||||
|
if (reader.Read()) {
|
||||||
|
rac = new cRac {
|
||||||
|
IDrac = Convert.ToInt64(reader["IDrac"]),
|
||||||
|
Title = reader["Title"].ToString(),
|
||||||
|
SubTitle = reader["SubTitle"].ToString(),
|
||||||
|
Creato = DateTime.Parse(reader["Creato"] as string),
|
||||||
|
Updated = DateTime.Parse(reader["Aggiornato"].ToString()),
|
||||||
|
Trama = reader["Trama"]?.ToString() ?? "",
|
||||||
|
Voto = reader["Voto"]?.ToString() ?? "Non Letto"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (rac == null) return null; // Racconto non trovato
|
||||||
|
|
||||||
|
// 2. Recupero Autori
|
||||||
|
rac.Autori = GetList(cn, "SELECT a.Autore FROM Autori a JOIN Links_Rac_Aut l ON a.IDaut = l.IDaut WHERE l.IDrac = @IDrac", IDrac);
|
||||||
|
|
||||||
|
// 3. Recupero Tags
|
||||||
|
rac.Tags = GetList(cn, "SELECT t.Tag FROM Tags t JOIN Links_Rac_Tag l ON t.IDtag = l.IDtag WHERE l.IDrac = @IDrac", IDrac);
|
||||||
|
|
||||||
|
// 4. Recupero Origini
|
||||||
|
rac.Origini = GetList(cn, "SELECT o.Origine FROM Origini o JOIN Links_Rac_Ori l ON o.IDori = l.IDori WHERE l.IDrac = @IDrac", IDrac);
|
||||||
|
|
||||||
|
// 5. Recupero Note (Key-Value)
|
||||||
|
string queryNotes = @"
|
||||||
|
SELECT n.NKey, n.NVal
|
||||||
|
FROM Notes n
|
||||||
|
JOIN Links_Rac_Not l ON n.IDnot = l.IDnot
|
||||||
|
WHERE l.IDrac = @IDrac";
|
||||||
|
using (var cmd = new SQLiteCommand(queryNotes, cn)) {
|
||||||
|
cmd.Parameters.AddWithValue("@IDrac", IDrac);
|
||||||
|
using (var reader = cmd.ExecuteReader()) {
|
||||||
|
while (reader.Read()) {
|
||||||
|
cNota nt = new cNota(reader["NKey"].ToString(), reader["NVal"].ToString());
|
||||||
|
rac.Notes.Add(nt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 6. Recupero Segnalini
|
||||||
|
// string querySng = @"
|
||||||
|
// SELECT s.Linea, s.Segnalino
|
||||||
|
// FROM Segnalini s
|
||||||
|
// JOIN Links_Rac_Sng l ON s.IDsng = l.IDsng
|
||||||
|
// WHERE l.IDrac = @IDrac";
|
||||||
|
// using (var cmd = new SQLteCommand(querySng, cn) {
|
||||||
|
// cmd.Parameters.AddWithValue("@IDrac", IDrac);
|
||||||
|
// using (var reader = cmd.ExecuteReader()) {
|
||||||
|
// while (reader.Read()) {
|
||||||
|
// rac.Segnalini.Add(new SegnalinoInfo {
|
||||||
|
// Linea = Convert.ToInt32(reader["Linea"]),
|
||||||
|
// Descrizione = reader["Segnalino"].ToString()
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
return rac;
|
||||||
|
|
||||||
|
}//lock
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Importa il racconto passato sul DB
|
/// Importa il racconto passato sul DB
|
||||||
@@ -1728,6 +1825,19 @@ namespace A69WD {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Helper per la lettura rapida di liste di stringhe
|
||||||
|
public static List<string> GetList(SQLiteConnection conn, string sql, long IDrac) {
|
||||||
|
var list = new List<string>();
|
||||||
|
using (var cmd = new SQLiteCommand(sql, conn)) {
|
||||||
|
cmd.Parameters.AddWithValue("@IDrac", IDrac);
|
||||||
|
using (var reader = cmd.ExecuteReader()) {
|
||||||
|
while (reader.Read()) list.Add(reader.GetValue(0).ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // class DBTools
|
} // class DBTools
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ namespace A69WD.Data {
|
|||||||
/// Default: ''
|
/// Default: ''
|
||||||
/// Mappa [SubTitle]
|
/// Mappa [SubTitle]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string SubTitle { get; set; } = "";
|
public string SubTitle { get; set; } = string.Empty;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data di creazione/pubblicazione del racconto o in mancanza di essa, data di inserimento del racconto in ATDB
|
/// Data di creazione/pubblicazione del racconto o in mancanza di essa, data di inserimento del racconto in ATDB
|
||||||
@@ -58,10 +58,10 @@ namespace A69WD.Data {
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Testo completo della trama del racconto
|
/// Testo completo della trama del racconto
|
||||||
/// Default: null
|
/// Default: ''
|
||||||
/// Mappa [Trama]
|
/// Mappa [Trama]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Trama { get; set; } = null;
|
public string Trama { get; set; } = string.Empty;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -83,21 +83,21 @@ namespace A69WD.Data {
|
|||||||
/// Default: null
|
/// Default: null
|
||||||
/// Mappa la relazione tramite [Links_Rac_Aut] con la tabella [Autori].
|
/// Mappa la relazione tramite [Links_Rac_Aut] con la tabella [Autori].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Autori { get; set; } = null;
|
public List<string> Autori { get; set; } = new List<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Elenco dei tag o proprietà associati (es. Genere, Mood).
|
/// Elenco dei tag o proprietà associati (es. Genere, Mood).
|
||||||
/// Default: null
|
/// Default: null
|
||||||
/// Mappa la relazione tramite [Links_Rac_Tag] con la tabella [Tags].
|
/// Mappa la relazione tramite [Links_Rac_Tag] con la tabella [Tags].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Tags { get; set; } = null;
|
public List<string> Tags { get; set; } = new List<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Elenco delle sorgenti o origini da cui proviene il racconto.
|
/// Elenco delle sorgenti o origini da cui proviene il racconto.
|
||||||
/// Default: null
|
/// Default: null
|
||||||
/// Mappa la relazione tramite [Links_Rac_Ori] con la tabella [Origini].
|
/// Mappa la relazione tramite [Links_Rac_Ori] con la tabella [Origini].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public List<string> Origini { get; set; } = null;
|
public List<string> Origini { get; set; } = new List<string>();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Note informative strutturate come coppia Chiave-Valore (es. Link, Resume).
|
/// Note informative strutturate come coppia Chiave-Valore (es. Link, Resume).
|
||||||
@@ -108,7 +108,7 @@ namespace A69WD.Data {
|
|||||||
/// Mappa la relazione tramite [Links_Rac_Not] con la tabella [Notes].
|
/// Mappa la relazione tramite [Links_Rac_Not] con la tabella [Notes].
|
||||||
/// </summary>
|
/// </summary>
|
||||||
//public Dictionary<string, string> Note { get; set; } = new Dictionary<string, string>();
|
//public Dictionary<string, string> Note { get; set; } = new Dictionary<string, string>();
|
||||||
public List<cNota> Notes { get; set; } = null;
|
public List<cNota> Notes { get; set; } = new List<cNota>();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@@ -184,18 +184,44 @@ namespace A69WD {
|
|||||||
private Service_Importer serviceImporter = null;
|
private Service_Importer serviceImporter = null;
|
||||||
|
|
||||||
private void btnTest_Click(object sender, EventArgs e) {
|
private void btnTest_Click(object sender, EventArgs e) {
|
||||||
int MaxRac = 60;
|
// Test dell'esportazione in html
|
||||||
pbST.Maximum = MaxRac;
|
//int MaxRac = 60;
|
||||||
pbST.Minimum = 0;
|
//pbST.Maximum = MaxRac;
|
||||||
pbST.Value = 0;
|
//pbST.Minimum = 0;
|
||||||
lblST.Text = "Inizio esportazione racconti";
|
//pbST.Value = 0;
|
||||||
for (int i = 0; i < 61; i++) {
|
//lblST.Text = "Inizio esportazione racconti";
|
||||||
cRac rac = App.DB.GetRacById(i);
|
//for (int i = 0; i < 61; i++) {
|
||||||
cRac.EsportaInHtml(rac, Cfg.Settings.PathDownloadWorking);
|
// cRac rac = App.DB.GetRacById(i);
|
||||||
pbST.Value = i;
|
// cRac.EsportaInHtml(rac, Cfg.Settings.PathDownloadWorking);
|
||||||
lblST.Text = $"Esportato racconto ID={rac.strIDrac}";
|
// pbST.Value = i;
|
||||||
|
// lblST.Text = $"Esportato racconto ID={rac.strIDrac}";
|
||||||
|
//}
|
||||||
|
//lblST.Text = $"Fine esportazione {MaxRac.ToString("000")} racconti";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Test funzione di lettura dal DB
|
||||||
|
Logger.Information("-- Start test 100*50 letture originali --");
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
for (int j = 0; j < 100; j++) {
|
||||||
|
for (int i = 1; i <= 50; i++) {
|
||||||
|
cRac rac = App.DB.GetRacById_Orig(i);
|
||||||
|
if (rac.IDrac != i) Logger.Information($"Letto ID={i.ToString()}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
lblST.Text = $"Fine esportazione {MaxRac.ToString("000")} racconti";
|
TimeSpan tp = start-DateTime.Now;
|
||||||
|
Logger.Information($" End test in {tp.ToString()}");
|
||||||
|
Logger.Information("-- Start test 100*50 letture nuove --");
|
||||||
|
start = DateTime.Now;
|
||||||
|
for (int j = 0; j < 100; j++) {
|
||||||
|
for (int i = 1; i <= 50; i++) {
|
||||||
|
cRac rac = App.DB.GetRacById(i);
|
||||||
|
if (rac.IDrac != i) Logger.Information($"Letto ID={i.ToString()}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tp = start - DateTime.Now;
|
||||||
|
Logger.Information($" End test in {tp.ToString()}");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user