I have a problem with the correct import of shape files into SQL when it comes to encoding of attributes. I found that none of tools like SAGA, QGIS, OSGeo4W,does it correctly. Mostly they create a varchar column instead of nvarchar. So I've written some code to create unicode SQL file based on any IFeatureSet, because DotSpatial ShapeFileReader properly read shape's codepage. Generated SQL file can be executed under SQLManager to create table and insert rows with unicode string encoding.
If anyone could suggest better ( one simple tool ) solution..
If anyone could suggest better ( one simple tool ) solution..
public static class SQLExporter
{
private static System.Collections.Hashtable dbTypeTable;
private static string ConvertToDbType(Type t)
{
if (dbTypeTable == null)
{
dbTypeTable = new System.Collections.Hashtable();
dbTypeTable.Add(typeof(System.Boolean), "bool");
dbTypeTable.Add(typeof(System.Byte), "smallint");
dbTypeTable.Add(typeof(System.Int16), "smallint");
dbTypeTable.Add(typeof(System.Int32), "int");
dbTypeTable.Add(typeof(System.Int64), "bigint");
dbTypeTable.Add(typeof(System.Double), "float");
dbTypeTable.Add(typeof(System.Decimal), "decimal");
dbTypeTable.Add(typeof(System.String), "nvarchar(MAX)");
dbTypeTable.Add(typeof(System.DateTime), "datetime2");
dbTypeTable.Add(typeof(System.Byte[]), "nvarbinary(MAX)");
dbTypeTable.Add(typeof(System.Guid), "UniqueIdentifier"
);
}
string dbtype;
try
{
dbtype = (string)dbTypeTable[t];
}
catch
{
dbtype = "nvarchar(max)";
}
return dbtype;
}
private static TextWriter ExportOpenSqlFile(string fileName, DataRow rowSpec)
{
string name = Path.GetFileNameWithoutExtension(fileName);
rowSpec.Table.TableName = name;
TextWriter tw = new StreamWriter(fileName + ".SQL", false, Encoding.Unicode);
StringBuilder sb = new StringBuilder();
sb.AppendLine(string.Format("DROP TABLE [{0}]", name));
sb.AppendLine("GO");
sb.AppendLine("--");
sb.AppendLine(string.Format("CREATE TABLE [{0}] (", name));
sb.AppendLine(" GId [uniqueidentifier] NOT NULL DEFAULT NEWID()");
sb.AppendLine(" ,IId INT IDENTITY (1, 1) NOT NULL");
sb.AppendLine(" ,SHAPE [sys].[geography] NOT NULL");
foreach (DataColumn c in rowSpec.Table.Columns)
{
sb.AppendLine(string.Format(" ,[{0}] {1} {2}",
c.ColumnName,
ConvertToDbType(c.DataType),
" NULL "
));
}
sb.AppendLine(") ON [PRIMARY] ");
sb.AppendLine("GO ");
sb.AppendLine("-- ");
sb.AppendLine("GO");
sb.AppendLine("--");
sb.AppendLine(string.Format("INSERT INTO [{0}] (", name));
sb.AppendLine(" [SHAPE],");
bool first = true;
foreach (DataColumn c in rowSpec.Table.Columns)
{
if (!first) sb.Append(", "); first = false;
sb.AppendLine(string.Format("[{0}]", c.ColumnName));
}
sb.AppendLine(") VALUES ");
tw.Write(sb.ToString());
tw.Flush();
return tw;
}
private static void ExportCloseSqlFile(TextWriter tw)
{
tw.Flush();
tw.Close();
}
public static void Export(IFeatureSet Layer, string name)
{
TextWriter tw = ExportOpenSqlFile(name, Layer.Features[0].DataRow);
StringBuilder sb = new StringBuilder();
ProjectionInfo p = Layer.Projection;
Layer.Reproject(KnownCoordinateSystems.Geographic.World.WGS1984);
bool first = true;
foreach (IFeature f in Layer.Features)
{
sb.Clear();
if (!first) sb.Append(",( "); else sb.Append(" ( ");
first = false;
//sb.Append("geography::STGeomFromWKB(" + f.BasicGeometry.ToBinary(). + ", 4326), ");
sb.Append("geography::STGeomFromText('" + f.BasicGeometry.ToString() + "', 4326), ");
bool firstcol = true;
foreach (object o in f.DataRow.ItemArray)
{
if (!firstcol) sb.Append(", "); firstcol = false;
if (o == null)
sb.Append("NULL");
else
if (o.GetType() == typeof(System.DBNull))
sb.Append("NULL");
else
if (o.GetType() == typeof(string))
sb.Append(string.Format("N'{0}'", o));
else
sb.Append(string.Format(CultureInfo.InvariantCulture, "{0}", o));
}
sb.AppendLine(")");
tw.Write(sb.ToString());
}
ExportCloseSqlFile(tw);
Layer.Reproject(p);
}
private void ExportLayer_Click(object sender, EventArgs e)
{
if (App.Map.Layers.SelectedLayer == null) return;
IFeatureSet layer = App.Map.Layers.SelectedLayer.DataSet as IFeatureSet;
if (layer == null) return;
if(layer.Features.Count==0) return;
SQLExporter.Export(layer, layer.Filename);
}