-
Notifications
You must be signed in to change notification settings - Fork 13
/
Program.cs
196 lines (168 loc) · 6.75 KB
/
Program.cs
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
using CommandLine;
using CommandLine.Text;
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using DbfDataReader;
using System.Data.Common;
using System.Text;
using System.ComponentModel.DataAnnotations;
using System.Linq;
namespace DbfBulkCopy
{
public class Program
{
public static int Main(string[] args)
{
Console.WriteLine($"");
return Parser.Default.ParseArguments<Options>(args)
.MapResult(
options => RunAndReturnExitCode(options),
_ => 1);
}
public static int RunAndReturnExitCode(Options options)
{
Console.WriteLine(HeadingInfo.Default);
Console.WriteLine();
Console.WriteLine("Bulk copy from:");
Console.WriteLine($" DBF: {options.Dbf}");
Console.WriteLine("to:");
Console.WriteLine($" Server: {options.Server}");
Console.WriteLine($" Database: {options.Database}");
Console.WriteLine($" Table: {options.Table}");
Console.WriteLine($" BulkCopyTimeout: {options.BulkCopyTimeout}");
Console.WriteLine($" Use SSPI: {options.UseSSPI}");
if (!options.UseSSPI)
Console.WriteLine($" UserID: {options.UserId}");
Console.WriteLine($" Truncate: {options.Truncate}");
Console.WriteLine($" SkipDeletedRecords: {options.SkipDeletedRecords}");
Console.WriteLine();
string connectionString;
if (options.UseSSPI)
connectionString = BuildConnectionStringSSPI(options);
else
connectionString = BuildConnectionString(options);
using (var connection = new SqlConnection(connectionString))
{
connection.Open();
if (options.Truncate)
{
TruncateTable(connection, options.Table);
}
DoBulkCopy(connection, options);
}
return 0;
}
private static void TruncateTable(SqlConnection connection, string table)
{
Console.WriteLine($"Truncating table '{table}'");
var sql = $"truncate table {table};";
var stopwatch = new Stopwatch();
stopwatch.Start();
var command = new SqlCommand(sql, connection);
command.ExecuteNonQuery();
stopwatch.Stop();
Console.WriteLine($"Truncating table '{table}' completed in {GetElapsedTime(stopwatch)}s");
}
private static void CreateTable(DbfDataReader.DbfDataReader dbfdr, SqlConnection connection, Options options)
{
try
{
StringBuilder query = new StringBuilder();
query.Append($"IF OBJECT_ID('{options.Table}', 'U') IS NOT NULL DROP TABLE {options.Table}; ");
query.Append("CREATE TABLE ");
query.Append(options.Table);
query.Append(" ( ");
var cs = dbfdr.GetColumnSchema();
for (int i = 0; i < cs.Count; i++)
{
var col = cs[i];
query.Append(col.ColumnName);
query.Append(" ");
query.Append(ConvertToSQLType(col));
if (i < cs.Count - 1)
query.Append(", ");
}
query.Append(")");
SqlCommand sqlQuery = new SqlCommand(query.ToString(), connection);
sqlQuery.ExecuteNonQuery();
}
catch(Exception ex)
{
Console.WriteLine($"Error creating table {ex.Message}");
}
}
private static string ConvertToSQLType(DbColumn col)
{
DbfColumn dcol = col as DbfColumn;
switch (dcol.DataType.Name)
{
case "String":
return $"varchar(max)";
// return $"char({dcol.Length})"; this yields an error
case "Int64":
return "bigint";
case "Int32":
return "int";
case "Boolean":
return "bit";
case "DateTime":
return "Datetime";
case "Decimal":
return $"Decimal({dcol.Length},{dcol.DecimalCount})";
default:
return col.DataType.Name;
}
}
private static void DoBulkCopy(SqlConnection connection, Options options)
{
Console.WriteLine("Begin bulk copy");
var stopwatch = new Stopwatch();
stopwatch.Start();
var rowsCopied = 0L;
var dbfRecordCount = 0L;
var dbfDataReaderOptions = new DbfDataReaderOptions
{
SkipDeletedRecords = options.SkipDeletedRecords
};
using (var dbfDataReader = new DbfDataReader.DbfDataReader(options.Dbf, dbfDataReaderOptions))
{
dbfRecordCount = dbfDataReader.DbfTable.Header.RecordCount;
using (var bulkCopy = new SqlBulkCopy(connection))
{
bulkCopy.BulkCopyTimeout = options.BulkCopyTimeout;
bulkCopy.DestinationTableName = options.Table;
if (options.CreateTable)
{
CreateTable(dbfDataReader, connection, options);
}
try
{
bulkCopy.WriteToServer(dbfDataReader);
rowsCopied = bulkCopy.RowsCopied();
}
catch (Exception ex)
{
Console.WriteLine($"Error importing: dbf file: '{options.Dbf}', exception: {ex.Message}");
}
}
}
stopwatch.Stop();
Console.WriteLine($"Bulk copy completed in {GetElapsedTime(stopwatch)}s");
Console.WriteLine($"Copied {rowsCopied} of {dbfRecordCount} rows");
}
private static string GetElapsedTime(Stopwatch stopwatch)
{
var ts = stopwatch.Elapsed;
return $"{ts.Hours:00}:{ts.Minutes:00}:{ts.Seconds:00}.{ts.Milliseconds / 10:00}";
}
private static string BuildConnectionString(Options options)
{
return $"Server={options.Server};Database={options.Database};User ID={options.UserId};Password={options.Password};";
}
private static string BuildConnectionStringSSPI(Options options)
{
return $"Server={options.Server};Database={options.Database};Integrated Security=SSPI;";
}
}
}