1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
|
//using System.Data;
//using System.Data.SqlClient;
//using System.IO;
private void CSV_XML_nach_Datenbank(String dateiPfad, String ZielTabelle, SqlConnection con)
{
//knoxyz 14.11.2008
try
{
DateTime startzeit = System.DateTime.Now;
//stellt Vermittler zwischen DatenQuelle(sqlServer) und DatenZiel(DataSet/DataTable) dar
SqlDataAdapter da = new SqlDataAdapter();
//enthält Tabellen
DataSet ds = new DataSet();
SqlCommand cmd = new SqlCommand(); //der sqlCommand nimmt SQL-Befehle entgegen
cmd.Connection = con; //generell festlegen, für welche Datenbank er diese Befehle ausführen soll
//ggf Verbindung herstellen
if (con.State != ConnectionState.Open) con.Open();
String schemaPfad = Application.StartupPath + @"\Schema_" + ZielTabelle + ".xsd";
//(Optional) Per TableMapping können Tabellen einen Namen gegeben werden. Alte Einträge entfernen
da.TableMappings.Clear();
//Welche Datenbankt
cmd.CommandText = "SELECT * FROM " + ZielTabelle;
da.SelectCommand = cmd;
da.TableMappings.Add("Table", ZielTabelle);
ds.Clear();
if (File.Exists(schemaPfad) == false) //Fall keine Schemadatei vorhanden ist, jetzt eine erstellen
{ //sofern Änderungen an der Datenbank gemacht wurden, die Schema.xsd einfach löschen
da.Fill(ds); //Tabellen des DataAdapter in ein DataSet schreiben
da.FillSchema(ds, SchemaType.Source); //Schema(Aufbau) der SQL-Tabellen auch im DataSet übernehmen
ds.WriteXmlSchema(schemaPfad); //Schema lokal speichern
}
//ds.WriteXml(schemaPfad + ".xml");//Schema und Daten lokal speichern (BackUp)
//Ziel-SQL-Tabelle
// anders als hier, schicke ich die Daten erst an eine Temp-Tabelle, die den gleichen Aufbau wie die eigentliche Ziel-Tabelle hat,
// und frage per Exist-Befehl anhand verschiedener Kriterien ab, ob Datensätze evtl. in der Ziel-Tab bereits vorhanden sind.
DataTable dt = new DataTable("Artikelstamm");
//um zu überprüfen ob die CVS-Daten zur SQL-Tabelle passen, hier das Schema der Datenbank übergeben
dt.ReadXmlSchema(schemaPfad);
//festlegen wo die CSV zu finden ist, die wir an die Datenbank schicken wollen
//Wurde eine eine 'xml-Datei' ausgesucht..
if (dateiPfad.EndsWith(".xml", StringComparison.OrdinalIgnoreCase))
{
dt.ReadXml(dateiPfad);
}
else
{
if (//...oder CSV/Textdatei?
(dateiPfad.EndsWith(".csv", StringComparison.OrdinalIgnoreCase))
|| (dateiPfad.EndsWith(".txt", StringComparison.OrdinalIgnoreCase))
)
{
StreamReader DateiLeser = new StreamReader(dateiPfad, System.Text.Encoding.Default);
//Die nachfolgende Replace-Aufrufe entfernen Sonderzeichen, die mögliche Probleme verursachen könnten
//Spaltenüberschriften auslesen und ggf. Punkte mit Unterstrich ersetzen
String Zeileninhalt = DateiLeser.ReadLine().Replace(".", "_").Replace("\t", ";");
DateiLeser.ReadLine(); //Leerzeile falls Daten erst in 3ter Zeile beginnen
char trennzeichen = ';';
//Der Inhalt der CSV-Datei wird Zeile für Zeile ausgelesen und in eine DataTable geschrieben
while (DateiLeser.EndOfStream == false)
{
Zeileninhalt = DateiLeser.ReadLine().Replace("'", "").Replace(";", "").Replace("=", "").Replace("\"", "");
Zeileninhalt = Zeileninhalt.Replace("\t", ";").Substring(0, Zeileninhalt.Length - 1);
//Zeileninhalt = Zeileninhalt.Replace("\t", ";"); //je nach CSV-Aufbau, diese oder Zeile darüber benutzen
//Inhalt einer Zeilen in Teilstrings zerlegen.
String[] csvZeilenInhalt = Zeileninhalt.Split(trennzeichen);
dt.Rows.Add(csvZeilenInhalt);
}
DateiLeser.Close();
}
else { MessageBox.Show("ungültige Datei ausgesucht", "falscher Dateityp"); }
}
if (dt.Rows.Count > 0) //wurden Daten aus der Quelldatei in DataTable kopiert?
{
//Jetzt liegt der Inhalt der CSV-Datei, auf Datentypen geprüft und mit Schema,
// im DataTable und kann in einem Rutsch (als Objekt) an den Datenbank-Server geschickt werden :-)
SqlBulkCopy bcopy = new SqlBulkCopy(con);
bcopy.DestinationTableName = ZielTabelle;
bcopy.WriteToServer(dt);
//dt.WriteXml(dateiPfad + ".xml"); //csv als xml speichern
String dauer = new DateTime(System.DateTime.Now.Ticks - startzeit.Ticks).ToString("mm 'Minuten und' ss 'Sekunden'");
MessageBox.Show(dt.Rows.Count + " Zeilen wurden in " + dauer + " verarbeitet :-)",
"Import war erfolgreich :-)");
dt.Clear();
//try
//{
//(optional) Log-Datei der Datenbank verkleinern
//cmd.CommandText = "DBCC SHRINKDATABASE(N'" + con.Database + "' )";
//cmd.ExecuteNonQuery();
//}
//catch (Exception e) { MessageBox.Show(e.Message); }
}
}
catch (Exception importFehler)
{
MessageBox.Show(importFehler.Message, "Import-Fehler");
}
}
//Hier folgt ein Beispiel wie die Methode aufgerufen werden könnte
private void BeispielZumAufrufDerImportMethode_Click(object sender, EventArgs e)
{ //Vorbereitung
String zielTabelle = "Artikelstamm";
String dateiPfad = String.Empty;
OpenFileDialog dateiAuswaehlen = new OpenFileDialog();
dateiAuswaehlen.Filter = "csv-Datei (*.txt)|*.txt"
+ "|xml-Datei (*.xml)|*.xml"
+ "|alle Dateien (*.*)|*.*";
dateiAuswaehlen.Title = zielTabelle;
if (dateiAuswaehlen.ShowDialog() == DialogResult.OK) dateiPfad = dateiAuswaehlen.FileName;
//Verbindungsaufbau definieren
SqlConnectionStringBuilder conBuilder = new SqlConnectionStringBuilder();
conBuilder.DataSource = "(local)"; //kann auch eine IP oder Name sein, dann ohne Klammern
conBuilder.InitialCatalog = "knoxyz";
conBuilder.ConnectTimeout = 10;
conBuilder.IntegratedSecurity = true; //oder User & Password
//conBuilder.UserID = "knoxyz";
//conBuilder.Password = "xyz";
SqlConnection con = new SqlConnection(conBuilder.ConnectionString);
//Prüfen ob Parameter Werte haben, falls nicht kein Aufruf
if ((dateiPfad != String.Empty) && (zielTabelle.Trim() != "") && (con.ConnectionString != ""))
CSV_XML_nach_Datenbank(dateiPfad, zielTabelle, con);
else MessageBox.Show("ParameterWerte für DB-Import stimmen nicht");
}
|