diff --git a/Src/A69WD/Data/DBTools.cs b/Src/A69WD/Data/DBTools.cs
index e0b4cff..33d17db 100644
--- a/Src/A69WD/Data/DBTools.cs
+++ b/Src/A69WD/Data/DBTools.cs
@@ -867,7 +867,7 @@ namespace A69WD {
///
/// Identificativo del racconto desiderato
/// Ritorna il racconto estratto dal DB
- public cRac GetRacById(long IDrac) {
+ public cRac GetRacById_Orig(long IDrac) {
lock (objLock) {
cRac rac = null;
List 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
+ }
///
/// Importa il racconto passato sul DB
@@ -1728,6 +1825,19 @@ namespace A69WD {
+ // Helper per la lettura rapida di liste di stringhe
+ public static List GetList(SQLiteConnection conn, string sql, long IDrac) {
+ var list = new List();
+ 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
diff --git a/Src/A69WD/Data/cRac.cs b/Src/A69WD/Data/cRac.cs
index 3557c59..c4b0c9e 100644
--- a/Src/A69WD/Data/cRac.cs
+++ b/Src/A69WD/Data/cRac.cs
@@ -36,7 +36,7 @@ namespace A69WD.Data {
/// Default: ''
/// Mappa [SubTitle]
///
- public string SubTitle { get; set; } = "";
+ public string SubTitle { get; set; } = string.Empty;
///
/// 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 {
///
/// Testo completo della trama del racconto
- /// Default: null
+ /// Default: ''
/// Mappa [Trama]
///
- public string Trama { get; set; } = null;
+ public string Trama { get; set; } = string.Empty;
#endregion
@@ -83,21 +83,21 @@ namespace A69WD.Data {
/// Default: null
/// Mappa la relazione tramite [Links_Rac_Aut] con la tabella [Autori].
///
- public List Autori { get; set; } = null;
+ public List Autori { get; set; } = new List();
///
/// Elenco dei tag o proprietà associati (es. Genere, Mood).
/// Default: null
/// Mappa la relazione tramite [Links_Rac_Tag] con la tabella [Tags].
///
- public List Tags { get; set; } = null;
+ public List Tags { get; set; } = new List();
///
/// Elenco delle sorgenti o origini da cui proviene il racconto.
/// Default: null
/// Mappa la relazione tramite [Links_Rac_Ori] con la tabella [Origini].
///
- public List Origini { get; set; } = null;
+ public List Origini { get; set; } = new List();
///
/// 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].
///
//public Dictionary Note { get; set; } = new Dictionary();
- public List Notes { get; set; } = null;
+ public List Notes { get; set; } = new List();
#endregion
diff --git a/Src/A69WD/UI/frmDownloader.cs b/Src/A69WD/UI/frmDownloader.cs
index e3b966f..4eabc09 100644
--- a/Src/A69WD/UI/frmDownloader.cs
+++ b/Src/A69WD/UI/frmDownloader.cs
@@ -184,18 +184,44 @@ namespace A69WD {
private Service_Importer serviceImporter = null;
private void btnTest_Click(object sender, EventArgs e) {
- int MaxRac = 60;
- pbST.Maximum = MaxRac;
- pbST.Minimum = 0;
- pbST.Value = 0;
- lblST.Text = "Inizio esportazione racconti";
- for (int i = 0; i < 61; i++) {
- cRac rac = App.DB.GetRacById(i);
- cRac.EsportaInHtml(rac, Cfg.Settings.PathDownloadWorking);
- pbST.Value = i;
- lblST.Text = $"Esportato racconto ID={rac.strIDrac}";
+ // Test dell'esportazione in html
+ //int MaxRac = 60;
+ //pbST.Maximum = MaxRac;
+ //pbST.Minimum = 0;
+ //pbST.Value = 0;
+ //lblST.Text = "Inizio esportazione racconti";
+ //for (int i = 0; i < 61; i++) {
+ // cRac rac = App.DB.GetRacById(i);
+ // cRac.EsportaInHtml(rac, Cfg.Settings.PathDownloadWorking);
+ // 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()}");
+
}