As promised, I have uploaded the data provider code I mentioned earlier to the SharpMap site. It’s written in C#. I took the existing Oracle provider, stripped out the Oracle SQL and put in T-SQL. There are a couple of things I’m still trying to chase down but it’s basically done at this point. I know they’re busy trying to finish up SharpMap 2.0 so I don’t know how long it’ll take to become available. Just in case, here’s the code:
[sourcecode language=’csharp’]
// Copyright 2008 – William Dollins
// SQL Server 2008 by William Dollins (dollins.bill@gmail.com)
// Based on Oracle provider by Humberto Ferreira (humbertojdf@hotmail.com)
//
// Date 2007-11-28
//
// This file is part of SharpMap.
// SharpMap is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// SharpMap is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public License
// along with SharpMap; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Data.SqlClient;
namespace SharpMap.Data.Providers
{
///
///
///
///
/// Adding a datasource to a layer:
///
/// SharpMap.Layers.VectorLayer myLayer = new SharpMap.Layers.VectorLayer("My layer");
/// string ConnStr = "Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=myDB;Data Source=myServermyInstance";
/// myLayer.DataSource = new SharpMap.Data.Providers.Katmai(ConnStr, "myTable", "GeomColumn", "OidColumn");
///
///
///
[Serializable]
public class Katmai : SharpMap.Data.Providers.IProvider, IDisposable
{
///
///
/// Connectionstring
/// Name of data table
/// Name of geometry column
/// /// Name of column with unique identifier
public Katmai(string ConnectionStr, string tablename, string geometryColumnName, string OID_ColumnName)
{
//Provider=SQLOLEDB.1;Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=ztTest;Data Source=
this.ConnectionString = ConnectionStr;
this.Table = tablename;
this.GeometryColumn = geometryColumnName;
this.ObjectIdColumn = OID_ColumnName;
}
///
///
/// Connectionstring
/// Name of data table
/// Name of column with unique identifier
public Katmai(string ConnectionStr, string tablename, string OID_ColumnName) : this(ConnectionStr,tablename,””,OID_ColumnName)
{
this.GeometryColumn = “shape”;
}
private bool _IsOpen;
///
///
public bool IsOpen
{
get { return _IsOpen; }
}
///
///
public void Open()
{
//Don’t really do anything.
_IsOpen = true;
}
///
///
public void Close()
{
//Don’t really do anything.
_IsOpen = false;
}
#region Disposers and finalizers
private bool disposed = false;
///
///
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
internal void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
//Close();
}
disposed = true;
}
}
///
///
~Katmai()
{
Dispose();
}
#endregion
private string _ConnectionString;
///
///
public string ConnectionString
{
get { return _ConnectionString; }
set { _ConnectionString = value; }
}
private string _Table;
///
///
public string Table
{
get { return _Table; }
set { _Table = value; }
}
private string _GeometryColumn;
///
///
public string GeometryColumn
{
get { return _GeometryColumn; }
set { _GeometryColumn = value; }
}
private string _ObjectIdColumn;
///
///
public string ObjectIdColumn
{
get { return _ObjectIdColumn; }
set { _ObjectIdColumn = value; }
}
///
///
///
///
public Collection
{
Collection
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
//Get bounding box string
string strBbox = GetBoxFilterStr(bbox);
string strSQL = “SELECT g.” + this.GeometryColumn +”.STAsBinary() “;
strSQL += ” FROM ” + this.Table + ” g WHERE “;
if (!String.IsNullOrEmpty(_defintionQuery))
strSQL += this.DefinitionQuery + ” AND “;
strSQL += strBbox;
using (SqlCommand command = new SqlCommand(strSQL, conn))
{
conn.Open();
using (SqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
if (dr[0] != DBNull.Value)
{
SharpMap.Geometries.Geometry geom = SharpMap.Converters.WellKnownBinary.GeometryFromWKB.Parse((byte[])dr[0]);
if(geom!=null)
features.Add(geom);
}
}
}
conn.Close();
}
}
return features;
}
///
///
/// Object ID
///
public SharpMap.Geometries.Geometry GetGeometryByID(uint oid)
{
SharpMap.Geometries.Geometry geom = null;
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
string strSQL = “SELECT g.” + this.GeometryColumn + “.STAsBinary() FROM ” + this.Table + ” g WHERE ” + this.ObjectIdColumn + “='” + oid.ToString() + “‘”;
conn.Open();
using (SqlCommand command = new SqlCommand(strSQL, conn))
{
using (SqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
if (dr[0] != DBNull.Value)
geom = SharpMap.Converters.WellKnownBinary.GeometryFromWKB.Parse((byte[])dr[0]);
}
}
}
conn.Close();
}
return geom;
}
///
///
///
///
public Collection
{
Collection
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
//Get bounding box string
string strBbox = GetBoxFilterStr(bbox);
string strSQL = “SELECT g.” + this.ObjectIdColumn + ” “;
strSQL += “FROM ” + this.Table + ” g WHERE “;
if (!String.IsNullOrEmpty(_defintionQuery))
strSQL += this.DefinitionQuery + ” AND “;
strSQL += strBbox;
using (SqlCommand command = new SqlCommand(strSQL, conn))
{
conn.Open();
using (SqlDataReader dr = command.ExecuteReader())
{
while (dr.Read())
{
if (dr[0] != DBNull.Value)
{
uint ID = (uint)(decimal)dr[0];
objectlist.Add(ID);
}
}
}
conn.Close();
}
}
return objectlist;
}
///
///
///
///
private string GetBoxFilterStr(SharpMap.Geometries.BoundingBox bbox) {
//geography::STGeomFromText(‘LINESTRING(47.656 -122.360, 47.656 -122.343)’, 4326);
SharpMap.Geometries.LinearRing lr = new SharpMap.Geometries.LinearRing();
lr.Vertices.Add(new SharpMap.Geometries.Point(bbox.Left, bbox.Bottom));
lr.Vertices.Add(new SharpMap.Geometries.Point(bbox.Right, bbox.Bottom));
lr.Vertices.Add(new SharpMap.Geometries.Point(bbox.Right, bbox.Top));
lr.Vertices.Add(new SharpMap.Geometries.Point(bbox.Left, bbox.Top));
lr.Vertices.Add(new SharpMap.Geometries.Point(bbox.Left, bbox.Bottom));
SharpMap.Geometries.Polygon p = new SharpMap.Geometries.Polygon(lr);
string bboxText = SharpMap.Converters.WellKnownText.GeometryToWKT.Write((SharpMap.Geometries.IGeometry)p); // “”;
string whereClause = this.GeometryColumn + “.STIntersects(geometry::STGeomFromText(‘” + bboxText + “‘, ” + this.SRID.ToString() + “)) = 1”;
return whereClause; // strBbox;
}
///
///
///
/// FeatureDataSet to fill data into
public void ExecuteIntersectionQuery(SharpMap.Geometries.Geometry geom, FeatureDataSet ds)
{
List
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
//TODO: Convert to SQL Server
string strGeom = “geography::STGeomFromText(‘” + geom.AsText() + “‘, #SRID#)”;
if (this.SRID > 0) {
strGeom = strGeom.Replace(“#SRID#”, this.SRID.ToString());
} else {
strGeom = strGeom.Replace(“#SRID#”, “0”);
}
strGeom = this.GeometryColumn + “.STIntersects(” + strGeom + “) = 1”;
string strSQL = “SELECT g.* , g.” + this.GeometryColumn + “).STAsBinary() As sharpmap_tempgeometry FROM ” + this.Table + ” g WHERE “;
if (!String.IsNullOrEmpty(_defintionQuery))
strSQL += this.DefinitionQuery + ” AND “;
strSQL += strGeom;
using (SqlDataAdapter adapter = new SqlDataAdapter(strSQL, conn))
{
conn.Open();
adapter.Fill(ds);
conn.Close();
if (ds.Tables.Count > 0)
{
FeatureDataTable fdt = new FeatureDataTable(ds.Tables[0]);
foreach (System.Data.DataColumn col in ds.Tables[0].Columns)
if (col.ColumnName != this.GeometryColumn && col.ColumnName != “sharpmap_tempgeometry”)
fdt.Columns.Add(col.ColumnName, col.DataType, col.Expression);
foreach (System.Data.DataRow dr in ds.Tables[0].Rows)
{
SharpMap.Data.FeatureDataRow fdr = fdt.NewRow();
foreach (System.Data.DataColumn col in ds.Tables[0].Columns)
if (col.ColumnName != this.GeometryColumn && col.ColumnName != “sharpmap_tempgeometry”)
fdr[col.ColumnName] = dr[col];
fdr.Geometry = SharpMap.Converters.WellKnownBinary.GeometryFromWKB.Parse((byte[])dr[“sharpmap_tempgeometry”]);
fdt.AddRow(fdr);
}
ds.Tables.Add(fdt);
}
}
}
}
///
///
///
///
private SharpMap.Geometries.LineString WktToLineString(string WKT)
{
SharpMap.Geometries.LineString line = new SharpMap.Geometries.LineString();
WKT = WKT.Substring(WKT.LastIndexOf(‘(‘) + 1).Split(‘)’)[0];
string[] strPoints = WKT.Split(‘,’);
foreach (string strPoint in strPoints)
{
string[] coord = strPoint.Split(‘ ‘);
line.Vertices.Add(new SharpMap.Geometries.Point(double.Parse(coord[0], SharpMap.Map.numberFormat_EnUS), double.Parse(coord[1], SharpMap.Map.numberFormat_EnUS)));
}
return line;
}
///
///
///
public int GetFeatureCount()
{
int count = 0;
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
string strSQL = “SELECT COUNT(*) FROM ” + this.Table;
if (!String.IsNullOrEmpty(_defintionQuery))
strSQL += ” WHERE ” + this.DefinitionQuery;
using (SqlCommand command = new SqlCommand(strSQL, conn))
{
conn.Open();
count = (int)command.ExecuteScalar();
conn.Close();
}
}
return count;
}
#region IProvider Members
private string _defintionQuery;
///
///
public string DefinitionQuery
{
get { return _defintionQuery; }
set { _defintionQuery = value; }
}
///
///
public System.Data.DataColumnCollection Columns
{
get {
throw new NotImplementedException();
}
}
private int _srid = 0;
///
///
public int SRID
{
get {
return _srid;
}
set {
_srid = value;
}
}
///
///
///
///
public SharpMap.Data.FeatureDataRow GetFeature(uint RowID)
{
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
string strSQL = “select g.* , g.” + this.GeometryColumn + “.STAsBinary() As sharpmap_tempgeometry from ” + this.Table + ” g WHERE ” + this.ObjectIdColumn + “=” + RowID.ToString() + “”;
using (SqlDataAdapter adapter = new SqlDataAdapter(strSQL, conn))
{
FeatureDataSet ds = new FeatureDataSet();
conn.Open();
adapter.Fill(ds);
conn.Close();
if (ds.Tables.Count > 0)
{
FeatureDataTable fdt = new FeatureDataTable(ds.Tables[0]);
foreach (System.Data.DataColumn col in ds.Tables[0].Columns)
if (col.ColumnName != this.GeometryColumn && col.ColumnName != “sharpmap_tempgeometry”)
fdt.Columns.Add(col.ColumnName, col.DataType, col.Expression);
if(ds.Tables[0].Rows.Count>0)
{
System.Data.DataRow dr = ds.Tables[0].Rows[0];
SharpMap.Data.FeatureDataRow fdr = fdt.NewRow();
foreach (System.Data.DataColumn col in ds.Tables[0].Columns)
if (col.ColumnName != this.GeometryColumn && col.ColumnName != “sharpmap_tempgeometry”)
fdr[col.ColumnName] = dr[col];
fdr.Geometry = SharpMap.Converters.WellKnownBinary.GeometryFromWKB.Parse((byte[])dr[“sharpmap_tempgeometry”]);
return fdr;
}
else
return null;
}
else
return null;
}
}
}
///
///
///
public SharpMap.Geometries.BoundingBox GetExtents()
{
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
string strSQL = “SELECT g.” + this.GeometryColumn + “.STEnvelope().STAsText() FROM ” + this.Table + ” g “;
if (!String.IsNullOrEmpty(_defintionQuery))
strSQL += ” WHERE ” + this.DefinitionQuery;
using (SqlCommand command = new SqlCommand(strSQL, conn))
{
conn.Open();
//SharpMap.Geometries.Geometry geom = null;
SharpMap.Geometries.BoundingBox bx = null;
SqlDataReader dr = command.ExecuteReader();
while (dr.Read())
{
string wkt = dr.GetString(0); //[this.GeometryColumn];
SharpMap.Geometries.Geometry g = SharpMap.Converters.WellKnownText.GeometryFromWKT.Parse(wkt);
SharpMap.Geometries.BoundingBox bb = g.GetBoundingBox();
if (bx == null)
{
bx = bb;
}
else
{
bx = bx.Join(bb);
}
}
dr.Close();
conn.Close();
return bx;
}
}
}
///
///
public string ConnectionID
{
get { return _ConnectionString; }
}
#endregion
#region IProvider Members
///
///
/// view box
/// FeatureDataSet to fill data into
public void ExecuteIntersectionQuery(SharpMap.Geometries.BoundingBox bbox, SharpMap.Data.FeatureDataSet ds)
{
List
using (SqlConnection conn = new SqlConnection(_ConnectionString))
{
//Get bounding box string
string strBbox = GetBoxFilterStr(bbox);
string strSQL = “SELECT g.*, g.” + this.GeometryColumn + “.Get_WKB() AS sharpmap_tempgeometry “;
strSQL += “FROM ” + this.Table + ” g WHERE “;
if (!String.IsNullOrEmpty(_defintionQuery))
strSQL += this.DefinitionQuery + ” AND “;
strSQL += strBbox;
using (SqlDataAdapter adapter = new SqlDataAdapter(strSQL, conn))
{
conn.Open();
System.Data.DataSet ds2 = new System.Data.DataSet();
adapter.Fill(ds2);
conn.Close();
if (ds2.Tables.Count > 0)
{
FeatureDataTable fdt = new FeatureDataTable(ds2.Tables[0]);
foreach (System.Data.DataColumn col in ds2.Tables[0].Columns)
if (col.ColumnName != this.GeometryColumn && col.ColumnName != “sharpmap_tempgeometry”)
fdt.Columns.Add(col.ColumnName,col.DataType,col.Expression);
foreach (System.Data.DataRow dr in ds2.Tables[0].Rows)
{
SharpMap.Data.FeatureDataRow fdr = fdt.NewRow();
foreach(System.Data.DataColumn col in ds2.Tables[0].Columns)
if (col.ColumnName != this.GeometryColumn && col.ColumnName != “sharpmap_tempgeometry”)
fdr[col.ColumnName] = dr[col];
fdr.Geometry = SharpMap.Converters.WellKnownBinary.GeometryFromWKB.Parse((byte[])dr[“sharpmap_tempgeometry”]);
fdt.AddRow(fdr);
}
ds.Tables.Add(fdt);
}
}
}
}
#endregion
}
}
[/sourcecode]
Hey Bill, any chance of adding Sql Geography type support?
I have considered it but it probably won’t happen soon due to current workload.
Hi Bill, It has taken a whilebut I have added this provider to SharpMap source tree (renamed to SqlServer2008)
Many thanks jd
John, Thank you! I didn’t know that was in the works. I’m glad you find it useful.
hiii….um using SharpMap 0.9 and i downloaded this PostGIS.cs from codeplex but i also encounter following error
Error1’SharpMap.Map’ does not contain a definition for ‘numberFormat_EnUS’ any help…?
Johannes,
Thanks for stopping by. I’m glad you’re trying to use the code.
I think I was working with a later build of SharpMap and there is a difference in the interface between versions. I looked at the source code for the “current release” and the IProvider interface defines the return type of those methods as a System.Collections.Generic.List.
If you browse the source code of the latest change set, you’ll see that the interface has been updated to use a return type of System.Collections.ObjectModel.Collection.
I would recommend downloading the latest source from CodePlex since there may be other differences as well.
Hi Bill, this is a great idea and I would love to implement it but I’m having trouble with the compilation. I’m using SharpMap 0.9 and get the errors mentioned below. Do I miss some depencies?
—————–
Error 1 ‘SharpMap.Data.Providers.Katmai’ does not implement interface member ‘SharpMap.Data.Providers.IProvider.GetGeometriesInView(SharpMap.Geometries.BoundingBox)’. ‘SharpMap.Data.Providers.Katmai.GetGeometriesInView(SharpMap.Geometries.BoundingBox)’ cannot implement ‘SharpMap.Data.Providers.IProvider.GetGeometriesInView(SharpMap.Geometries.BoundingBox)’ because it does not have the matching return type of ‘System.Collections.Generic.List’. C:UsersjkebeckDocumentsVisual Studio 2008WebSitesSampleDemosApp_CodeKatmai.cs 47 18 C:…SampleDemos
Error 2 ‘SharpMap.Data.Providers.Katmai’ does not implement interface member ‘SharpMap.Data.Providers.IProvider.GetObjectIDsInView(SharpMap.Geometries.BoundingBox)’. ‘SharpMap.Data.Providers.Katmai.GetObjectIDsInView(SharpMap.Geometries.BoundingBox)’ cannot implement ‘SharpMap.Data.Providers.IProvider.GetObjectIDsInView(SharpMap.Geometries.BoundingBox)’ because it does not have the matching return type of ‘System.Collections.Generic.List’. C:UsersjkebeckDocumentsVisual Studio 2008WebSitesSampleDemosApp_CodeKatmai.cs 47 18 C:…SampleDemos