Ich habe ein Legacy-System mit ungefähr 10 Millionen Zeilen in einer Tabelle. In dieser Tabelle gibt es eine Typenspalte text
, die meisten davon sind Standardtext, aber ungefähr 500.000 Zeilen enthalten RTF-Markups. Ich muss den RTF-formatierten Text in einfachen Text konvertieren.
Meine aktuelle Methode ist, dass ich ein C # -Programm habe, das die Abfrage mit a in eine DataTable lädt SqlDataAdapter
und das Winforms- RichTextBox
Steuerelement verwendet, um die Konvertierung durchzuführen .
void bw_DoWork(object sender, DoWorkEventArgs e)
{
count = 0;
rtbRTFToPlain = new RichTextBox();
using (SqlDataAdapter ada = new SqlDataAdapter("select note_guid, notes from client_notes", Globals.SQLConnectionString))
using(SqlCommandBuilder cmb = new SqlCommandBuilder(ada))
{
DataTable dt = new DataTable();
ada.UpdateCommand = cmb.GetUpdateCommand();
ada.Fill(dt);
int reportEvery = dt.Rows.Count / 100;
if (reportEvery == 0)
reportEvery = 1;
foreach (DataRow row in dt.Rows)
{
if (count % reportEvery == 0)
bw.ReportProgress(count / reportEvery);
try
{
if (((string)row["notes"]).TrimStart().StartsWith("{") == true)
{
rtbRTFToPlain.Rtf = (string)row["notes"];
row["notes"] = rtbRTFToPlain.Text;
}
}
catch
{
}
count++;
}
bw.ReportProgress(100);
this.Invoke(new Action(() =>
{
this.ControlBox = false;
this.Text = "Updating database please wait";
}));
ada.Update(dt);
}
}
Dies funktioniert hervorragend für kleine Tabellen, aber dies ist das erste Mal, dass ich es auf einer Tabelle mit einem so großen Datensatz ausführen musste (einige der RTF-Dateien können mit eingebetteten Bildern mehrere Megabyte groß sein), und ich erhalte OutOfMemory Fehler mit meinem C # -Programm.
Ich weiß, dass ich meine Abfrage in kleinere Stapel aufteilen kann, aber ich wollte herausfinden, ob es einen besseren Weg gibt, den ich vermisst habe, um die RTF-Formatierung zu entfernen.
Sollte ich genau das Gleiche tun wie meine aktuelle Lösung, aber immer nur kleinere Datenblöcke abfragen, oder gibt es einen besseren Weg, dies zu tun?
quelle
Ich habe das Gleiche wie Scott Chamberlain mit der Itenso RTF-DLL gemacht, aber in meinem Fall musste noch viel mehr Arbeit geleistet werden, bevor dies in meiner SQL 2008R2-Datenbank als SICHER markiert werden konnte.
Zuerst musste ich wie Scott den Verweis auf System.Drawing entfernen. Ich fand den einfachsten Weg, dies zu tun, indem ich die Referenz entfernte, neu kompilierte und dann die Codebits neu schrieb, die die Bibliothek verwendeten. In den meisten Fällen habe ich nur den gesamten Code aus den VOID-Funktionen entfernt, die ihn verwendet haben, und in Situationen, in denen ich Zeichnungs- / Farbobjekte nicht in "Objekt" -Objekte ändern konnte.
Das andere, was ich tun musste, war, alle Verweise auf log4net zu entfernen, da es auf eine Bibliothek System.DirectoryServices verweist, die auch nicht als sicher markiert werden kann. Das war etwas schwieriger, aber im Allgemeinen habe ich den gleichen Ansatz gewählt.
Nachdem ich das getan hatte, bekam ich Beschwerden über das Festlegen statischer Werte, was in einer SAFE CLR-Funktion nicht zulässig ist. Also habe ich den Code aktualisiert, um alle statischen Werte auf READONLY zu ändern, und das hat funktioniert (dies war so ziemlich alles im Abschnitt "Protokollierung" des Codes, der mir in keiner Weise wirklich wichtig war).
Mein endgültiger CLR-Code sah folgendermaßen aus:
quelle
Ich habe eine kleine SQL-Funktion geschrieben, die den Text aus markup-artigen Zeichenfolgen entfernt: http://cookingwithsql.com/index.php?option=com_content&task=view&id=65&Itemid=60
Leider werden nur Zeichenfolgendaten mit bis zu 8000 Zeichen verarbeitet. Möglicherweise könnte es geändert werden, um varchar (max) zu verwenden, wenn Sie mit SQL 2005 und höher arbeiten.
Verwendungszweck:
Ich werde die Quelle hier als Kurzreferenz veröffentlichen.
quelle
Wenn Sie einen DataReader anstelle einer DataTable verwenden, können Sie die Zeilen einzeln verarbeiten, anstatt alles in den Speicher zu laden. Das sollte Ihre Speicherfehler umgehen.
quelle