diff --git a/Src/A69WD/A69WD.csproj b/Src/A69WD/A69WD.csproj
index c18b60b..4fa7741 100644
--- a/Src/A69WD/A69WD.csproj
+++ b/Src/A69WD/A69WD.csproj
@@ -62,6 +62,7 @@
+
diff --git a/Src/A69WD/Data/DBTools.cs b/Src/A69WD/Data/DBTools.cs
index 33d17db..1b3e1a4 100644
--- a/Src/A69WD/Data/DBTools.cs
+++ b/Src/A69WD/Data/DBTools.cs
@@ -1071,106 +1071,6 @@ 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
///
@@ -1825,21 +1725,218 @@ 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());
+ // Metodi ricavati ottimizzando i miei tramite gemini
+
+ ///
+ /// Ricava il racconto con l'ID indicato leggendolo dal DB
+ ///
+ /// Indice identificativo del racconto voluto
+ /// oggetto cRac che rappresenta il racconto
+ 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) {
+ try {
+
+ 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 = Helper.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 = Helper.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 = Helper.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;
+
+ } catch (Exception ex) {
+ Logger.Error($"GetRacById({IDrac}) error: {ex.Message}");
+ return null;
}
- }
- return list;
+ }//lock
+ }
+
+ ///
+ /// Salva il racconto nel DB
+ ///
+ /// Racconto da salvare sul DB
+ /// Esito del salvataggio
+ public SaveResult SalvaRacconto(cRac racconto) {
+ lock (objLock) {
+ using (var transaction = cn.BeginTransaction()) {
+ try {
+
+ // 1. Inserimento Record Principale [Racconti]
+ var cmdRac = new SQLiteCommand(@"
+ INSERT INTO Racconti (Title, SubTitle, Creato, Aggiornato)
+ VALUES (@t, @st, @c, @a);
+ SELECT last_insert_rowid();",
+ cn, transaction);
+ cmdRac.Parameters.AddWithValue("@t", racconto.Title);
+ cmdRac.Parameters.AddWithValue("@st", racconto.SubTitle);
+ cmdRac.Parameters.AddWithValue("@c", racconto.Creato);
+ cmdRac.Parameters.AddWithValue("@a", racconto.Updated);
+
+ long newIDrac = (long)cmdRac.ExecuteScalar(); //
+ racconto.IDrac = newIDrac;
+
+ // 2. Salvataggio Relazioni Molti-a-Molti
+
+ // Inserimento Trama (Tabella [Trame])
+ if (!string.IsNullOrWhiteSpace(racconto.Trama)) {
+ var cmdTra = new SQLiteCommand("INSERT INTO Trame (IDrac, Trama) VALUES (@id, @txt)", cn, transaction);
+ cmdTra.Parameters.AddWithValue("@id", newIDrac);
+ cmdTra.Parameters.AddWithValue("@txt", racconto.Trama);
+ cmdTra.ExecuteNonQuery(); //
+ }
+
+ // Inserimento Voto (Tabella [Links_Rac_Vot])
+ if (!string.IsNullOrWhiteSpace(racconto.Voto)) {
+ var cmdVot = new SQLiteCommand("INSERT OR REPLACE INTO Links_Rac_Vot (IDrac, IDvot) VALUES (@r, @v)", cn, transaction);
+ cmdVot.Parameters.AddWithValue("@r", newIDrac);
+ cmdVot.Parameters.AddWithValue("@v", racconto.Voto); // IDvot corrisponde al valore rating
+ cmdVot.ExecuteNonQuery();
+ }
+
+ // 3. Salvataggio Relazioni Molti-a-Molti
+
+ // Autori
+ racconto.Autori.ForEach(autore => {
+ long idAut = Helper.GetOrCreateId(cn, transaction, "Autori", "Autore", "IDaut", autore);
+ Helper.ExecuteLink(cn, transaction, "Links_Rac_Aut", "IDaut", newIDrac, idAut);
+ });
+
+ // Tags
+ racconto.Tags.ForEach(tag => {
+ long idTag = Helper.GetOrCreateId(cn, transaction, "Tags", "Tag", "IDtag", tag);
+ Helper.ExecuteLink(cn, transaction, "Links_Rac_Tag", "IDtag", newIDrac, idTag);
+ });
+
+ // Origini Multiple
+ racconto.Origini.ForEach(origine => {
+ long idOri = Helper.GetOrCreateId(cn, transaction, "Origini", "Origine", "IDori", origine);
+ Helper.ExecuteLink(cn, transaction, "Links_Rac_Ori", "IDori", newIDrac, idOri);
+ });
+
+ // Note (Coppia Chiave-Valore)
+ foreach (var nota in racconto.Notes) {
+ var idNot = Helper.GetOrCreateNoteId(cn, transaction, nota.Key, nota.Description);
+ Helper.ExecuteLink(cn, transaction, "Links_Rac_Not", "IDnot", newIDrac, idNot);
+ }
+
+ // // 4. Inserimento Segnalini (Tabella [Segnalini])
+ // foreach (var sng in racconto.Segnalini) {
+ // var cmdSng = new SqliteCommand(@"
+ // INSERT INTO Segnalini (Linea, Segnalino) VALUES (@l, @s);
+ // SELECT last_insert_rowid();", connection, transaction);
+ // cmdSng.Parameters.AddWithValue("@l", sng.Linea);
+ // cmdSng.Parameters.AddWithValue("@s", sng.Descrizione);
+ // long idSng = (long)cmdSng.ExecuteScalar();
+ //
+ // // Link Segnalino al Racconto
+ // ExecuteLink(connection, transaction, "Links_Rac_Sng", "IDsng", newIDrac, idSng);
+ // }
+
+ transaction.Commit();
+ Logger.Information($"Inserito racconto {newIDrac}");
+ return SaveResult.Success;
+
+ } catch (Exception ex) {
+ transaction.Rollback();
+ Logger.Information($"Errore SQL durante l'inserimento del racconto racconto {racconto.Title}");
+ return SaveResult.GenericError;
+ }
+ }//transaction
+ }//lock
}
- } // class DBTools
+
+
+ } //class DBTools
}//namespace A69WD
diff --git a/Src/A69WD/Data/Helper.cs b/Src/A69WD/Data/Helper.cs
new file mode 100644
index 0000000..78c9ff1
--- /dev/null
+++ b/Src/A69WD/Data/Helper.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Data.SQLite;
+
+
+namespace A69WD.Data {
+
+ /*
+ *
+ * Questo file contiene i metodi statici per gestire le tabelle di lookup e i collegamenti.
+ * Nota che questi metodi accettano SqliteTransaction per operare all'interno del contesto della transazione principale.
+ *
+ * Vantaggi di questa suddivisione:
+ * - Helper statico: Non serve istanziare nulla per usare le funzioni di utilità.
+ * - Manutenibilità: Se cambi il modo in cui cerchi un autore, lo cambi in un solo punto (Helper.cs).
+ * - Transazioni pulite: DBTools.cs si occupa solo di aprire la transazione e chiamare in ordine i "mattoncini" forniti dall'Helper.
+ *
+ */
+ public static class Helper {
+ // Ottiene ID o crea nuovo record per Autori, Tags, Origini
+ public static long GetOrCreateId(SQLiteConnection conn, SQLiteTransaction trans, string table, string colName, string idCol, string value) {
+ var cmdSelect = new SQLiteCommand($"SELECT {idCol} FROM {table} WHERE {colName} = @v", conn, trans);
+ cmdSelect.Parameters.AddWithValue("@v", value);
+ var result = cmdSelect.ExecuteScalar();
+ if (result != null) return (long)result;
+
+ var cmdInsert = new SQLiteCommand($"INSERT INTO {table} ({colName}) VALUES (@v); SELECT last_insert_rowid();", conn, trans);
+ cmdInsert.Parameters.AddWithValue("@v", value);
+ return (long)cmdInsert.ExecuteScalar();
+ }
+
+
+ // Helper specifico per le Note (Key-Value)
+ public static long GetOrCreateNoteId(SQLiteConnection conn, SQLiteTransaction trans, string key, string val) {
+ var cmdSelect = new SQLiteCommand("SELECT IDnot FROM Notes WHERE NKey = @k AND NVal = @v", conn, trans);
+ cmdSelect.Parameters.AddWithValue("@k", key);
+ cmdSelect.Parameters.AddWithValue("@v", val);
+ var result = cmdSelect.ExecuteScalar();
+ if (result != null) return (long)result;
+
+ var cmdInsert = new SQLiteCommand("INSERT INTO Notes (NKey, NVal) VALUES (@k, @v); SELECT last_insert_rowid();", conn, trans);
+ cmdInsert.Parameters.AddWithValue("@k", key);
+ cmdInsert.Parameters.AddWithValue("@v", val);
+ return (long)cmdInsert.ExecuteScalar();
+ }
+
+ // Crea il legame nelle tabelle Links_...
+ public static void ExecuteLink(SQLiteConnection conn, SQLiteTransaction trans, string table, string targetIdCol, long idRac, long targetId) {
+ var cmd = new SQLiteCommand($"INSERT OR IGNORE INTO {table} (IDrac, {targetIdCol}) VALUES (@r, @t)", conn, trans);
+ cmd.Parameters.AddWithValue("@r", idRac);
+ cmd.Parameters.AddWithValue("@t", targetId);
+ cmd.ExecuteNonQuery();
+ }
+
+
+ // 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 Helper
+
+ public enum SaveResult {
+ Success = 0,
+ DatabaseConnectionError = 1,
+ MainRecordInsertError = 2,
+ TramaInsertError = 3,
+ RelationInsertError = 4,
+ SegnaliniInsertError = 5,
+ GenericError = 99
+ }
+
+
+}//namespace A69WD.Data
+
+
diff --git a/Src/A69WD/UI/frmDownloader.cs b/Src/A69WD/UI/frmDownloader.cs
index 4eabc09..cc3562d 100644
--- a/Src/A69WD/UI/frmDownloader.cs
+++ b/Src/A69WD/UI/frmDownloader.cs
@@ -183,45 +183,71 @@ namespace A69WD {
}
private Service_Importer serviceImporter = null;
- private void btnTest_Click(object sender, EventArgs e) {
- // 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";
+ private async void btnTest_Click(object sender, EventArgs e) {
+ // // 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()}");
- }
- }
- 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()}");
+ // // 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()}");
+ // }
+ // }
+ // 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()}");
+ // Test di salvataggio sul DB
+ // leggo 3 nuovi racconti
+ string file = @"C:\Commesse\_zPrivate\A69WD\Test\Down\A69_altro_Decisione-estrema_133364.html";
+ cLink_A69 lk = new cLink_A69(file, "A69_altro_Decisione-estrema_133364.html");
+ cRac rac1 = await lk.EstraiRac(file);
+ file = @"C:\Commesse\_zPrivate\A69WD\Test\Down\A69_altro_Decisione_133364 - Copy.html";
+ lk = new cLink_A69(file, "A69_altro_Decisione_133364 - Copy.html");
+ cRac rac2 = await lk.EstraiRac(file);
+ file = @"C:\Commesse\_zPrivate\A69WD\Test\Down\A69_altro_Dammi-un-bacio_153877.html";
+ lk = new cLink_A69(file, "A69_altro_Dammi-un-bacio_153877.html");
+ cRac rac3 = await lk.EstraiRac(file);
+ file = @"C:\Commesse\_zPrivate\A69WD\Test\Down\A69_altro_dammi-la-mano_157904.html";
+ lk = new cLink_A69(file, "A69_altro_dammi-la-mano_157904.html");
+ cRac rac4 = await lk.EstraiRac(file);
+ // // Controprova:
+ // var res1 = App.DB.ImportRac(rac1);
+ // var res2 = App.DB.ImportRac(rac2);
+ // var res3 = App.DB.ImportRac(rac3);
+ // var res4 = App.DB.ImportRac(rac4);
+ // Provo a salvarli
+ var res1 = App.DB.SalvaRacconto(rac1);
+ var res2 = App.DB.SalvaRacconto(rac2);
+ var res3 = App.DB.SalvaRacconto(rac3);
+ var res4 = App.DB.SalvaRacconto(rac4);
+
+ //
}