My featureSource:
**************************************************************
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;
using Teradata;
using Teradata.Client;
using Teradata.Client.Provider;
using System.Data.Common;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.ProviderBase;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;
namespace GisB20
{
class TDPointFeatureSource : FeatureSource
{
TdConnection cn;
TdConnectionStringBuilder cnsb = new TdConnectionStringBuilder();
//private OleDbConnection connection;
private string _tableName;
private string _Where_wo;
private string _Where_wi;
// It is important for compatability that you always have a default constructor that
// takes no parameters. This constructor will just chain to the more complex one.
public TDPointFeatureSource()
: this(string.Empty, string.Empty)
{ }
// We have provided another constructor that has all of the parameters we need for the FeatureSource
// to work.
public TDPointFeatureSource(string tableName, string where)
: base()
{
_tableName = tableName;
if (where != “”)
{
_Where_wi = " WHERE " + where;
_Where_wo = " AND " + where;
}
else
{
_Where_wi = “”;
_Where_wo = “”;
}
}
// The next dozen lines are all of the properties we need. It is good form to always match
// the parameters in your constructors with properties of the exact same name.
// Use the OpenCore to initialize your underlying data source. The concreat Open method will ensure
// that if the user calls the Open method multiple times in a row that you only get one call to
// OpenCore.
protected override void OpenCore()
{
System.Diagnostics.Debug.WriteLine(“begin:TDPointFeatureSource.OpenCore”);
cnsb.ConnectionTimeout = 1200;
cnsb.Database = “DBIPAD02”;
cnsb.DataSource = “GEDWI”;
cnsb.DataSourceDnsEntries = 8;
cnsb.Password = “Predict02”;
cnsb.ReadAhead = true;
cnsb.ResponseBufferSize = 1024 * 1000;
cnsb.UserId = “A09ZMZZ”;
cn = new TdConnection(cnsb.ToString());
cn.Open();
System.Diagnostics.Debug.WriteLine(“end:TDPointFeatureSource.OpenCore”);
}
// Use the CloseCore to close your underlying data source. It is important to note that the
// CloseCore is not like the Dispose on other objects. The FeatureSource is meant to be opened
// and closed many times durring its lifetime. Make sure that you clean up any objects that have
// unmanaged resources but do not put the object in a state that when Open is called it will fail.
// The concreat Close method will ensure that if the user calle the Close multiple times in
// a row that you only get one call to CloseCore.
protected override void CloseCore()
{
System.Diagnostics.Debug.WriteLine(“begin:TDPointFeatureSource.CloseCore”);
cn.Close();
System.Diagnostics.Debug.WriteLine(“end:TDPointFeatureSource.CloseCore”);
}
// Here you need to query all of the features in your data source. We use this method
// as the basis of nearly all other virtual methods. For example if you choose not to
// override the GetCountCore then we will get all the features and count them as the default.
// This is ineffecient however it produces the correct results.
protected override Collection<Feature> GetAllFeaturesCore(IEnumerable<string> columnNames)
{
TdCommand cmd = null;
TdDataReader reader = null;
Collection<Feature> returnFeatures = new Collection<Feature>();
System.Diagnostics.Debug.WriteLine("begin:TDPointFeatureSource.GetAllFeaturesCore " + _tableName);
// Alays be sure to wrap imporant code that accesses resources that need
// to be closed. In the Finally we will ensure they always get cleaned up.
try
{
// We need to construct the part of the SQL statement for retuning the
// column data. We only return the columns asked for byt the columnNames
// parameter of the function. This ensures we do not get more than we need.
string columnsSQL = string.Empty;
foreach (string columnName in columnNames)
{
columnsSQL += “,” + “"” + columnName + “"”;
}
if (columnsSQL.Length > 0)
columnsSQL = columnsSQL.Substring(1);
if (columnsSQL.Length == 0)
columnsSQL = " TG_ID, TG_X, TG_Y ";
if ((columnsSQL.Length > 0) && (!columnsSQL.Contains(“TG_ID”)))
columnsSQL = " TG_ID, TG_X, TG_Y, " + columnsSQL;
// Here we build up and execute the query string using the columns the users defined in the properties
// such as the XColumnName and IdColumnName.
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT " + columnsSQL + " FROM " + _tableName + _Where_wi;
cmd.Connection = cn;
reader = cmd.ExecuteReader();
// We now loop though all of the results and build up our features that we need to return.
while (reader.Read())
{
PointShape pointShape = new PointShape(Convert.ToDouble(reader[“TG_X”]), Convert.ToDouble(reader[“TG_Y”]));
pointShape.Id = reader[“TG_ID”].ToString();
Feature feature = pointShape.GetFeature();
// This small part populates the column values that were requested. They are data
// such as columns used for ClassBreakStyles or TextStyles for labeling.
foreach (string columnName in columnNames)
{
feature.ColumnValues.Add(columnName, reader[columnName].ToString());
}
returnFeatures.Add(feature);
}
}
finally
{
// Cleanup any of the objects that need to be closed or disposed.
if (cmd != null) { cmd.Dispose(); }
if (reader != null) { reader.Dispose(); }
}
System.Diagnostics.Debug.WriteLine(“end:TDPointFeatureSource.GetAllFeaturesCore”);
return returnFeatures;
}
// Though this method is not required for creating our new class it is an important one.
// This method is used to get only the features inside of the bounding box passed in. The reason
// this is critical is that many other methods on the QueryTools such as Touches, Overlaps, Intersects,
// and many others use this method as a first pass filter. If you do not override this method then
// the default code calls the GetAllFeatures and look at each to see if it is in the bounding box.
// While this method will produce the correct result it will not perform as well as your custom code.
protected override Collection<Feature> GetFeaturesInsideBoundingBoxCore(RectangleShape boundingBox, IEnumerable<string> returningColumnNames)
{
TdCommand cmd = null;
TdDataReader reader = null;
Collection<Feature> returnFeatures = new Collection<Feature>();
System.Diagnostics.Debug.WriteLine("begin:TDPointFeatureSource.GetFeaturesInsideBoundingBoxCore " + _tableName);
// Alays be sure to wrap imporant code that accesses resources that need
// to be closed. In the Finally we will ensure they always get cleaned up.
try
{
// We need to construct the part of the SQL statement for retuning the
// column data. We only return the columns asked for byt the columnNames
// parameter of the function. This ensures we do not get more than we need.
string columnsSQL = string.Empty;
foreach (string columnName in returningColumnNames)
{
columnsSQL += “,” + “"” + columnName + “"”;
}
if (columnsSQL.Length > 0)
columnsSQL = columnsSQL.Substring(1);
if (columnsSQL.Length == 0)
columnsSQL = " TG_ID, TG_X, TG_Y ";
if ((columnsSQL.Length > 0) && (!columnsSQL.Contains(“TG_ID”)))
columnsSQL = " TG_ID, TG_X, TG_Y, " + columnsSQL;
// This whereSql is important becasue it is what is used to determine if the point is in
// the bounding box passed in. While it is a bit complex it get your results quickly in
// large datasets so long as the X & Y columns are indexed.
string whereSql = "TG_X <= " + boundingBox.LowerRightPoint.X + " AND TG_X >= " + boundingBox.UpperLeftPoint.X + " AND TG_Y <= " + boundingBox.UpperLeftPoint.Y + " AND TG_Y >= " + boundingBox.LowerRightPoint.Y;
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT " + columnsSQL + " FROM " + _tableName + " WHERE " + whereSql + " " + _Where_wo;
cmd.Connection = cn;
reader = cmd.ExecuteReader();
// We now loop though all of the results and build up our features that we need to return.
while (reader.Read())
{
Feature feature = new Feature(Convert.ToDouble(reader[“TG_X”]), Convert.ToDouble(reader[“TG_Y”]), reader[“TG_ID”].ToString());
// This small part populates the column values that were requested. They are data
// such as columns used for ClassBreakStyles or TextStyles for labeling.
foreach (string columnName in returningColumnNames)
{
feature.ColumnValues.Add(columnName, reader[columnName].ToString());
}
returnFeatures.Add(feature);
}
}
finally
{
// Cleanup any of the objects that need to be closed or disposed.
if (cmd != null) { cmd.Dispose(); }
if (reader != null) { reader.Dispose(); }
}
System.Diagnostics.Debug.WriteLine(“end:TDPointFeatureSource.GetFeaturesInsideBoundingBoxCore”);
return returnFeatures;
}
// This method returns all of the columns in the data source. This method is not required however
// if it is not overridden then the FeatureSource will not have any columns available to it.
// Since having access to the column data is usefull for labeling and such we suggest you override it.
protected override Collection<FeatureSourceColumn> GetColumnsCore()
{
TdCommand cmd = null;
TdDataReader reader = null;
Collection<FeatureSourceColumn> returnColumns = new Collection<FeatureSourceColumn>();
System.Diagnostics.Debug.WriteLine("begin:TDPointFeatureSource.GetColumnsCore " + _tableName);
// Alays be sure to wrap imporant code that accesses resources that need
// to be closed. In the Finally we will ensure they always get cleaned up.
try
{
// Here we have a query that will quickly return nothing. As strange as it sounds it is a
// good way to get the table structure back without having to return any column data.
cmd = cn.CreateCommand();
cmd.CommandText = “SELECT * FROM " + _tableName + " WHERE 1=2”;
cmd.Connection = cn;
reader = cmd.ExecuteReader();
// We now loop through and create our column list. In the FeatureSourceColumn we can
// optionally provide the column type but it is just informational so we didn’t code it.
for (int i = 0; i < reader.FieldCount; i++)
{
FeatureSourceColumn featureSourceColumn = new FeatureSourceColumn(reader.GetName(i));
returnColumns.Add(featureSourceColumn);
}
}
finally
{
// Cleanup any of the objects that need to be closed or disposed.
if (cmd != null) { cmd.Dispose(); }
if (reader != null) { reader.Dispose(); }
}
System.Diagnostics.Debug.WriteLine(“end:TDPointFeatureSource.GetColumnsCore”);
return returnColumns;
}
// This is another method that does not need to be overridden but we suggest that you do.
// This method gets the cound of all the features in the data source. If you choose not to
// override it then the default will call the GetAllFeatures and count them. This is not very
// effecient so we suggest you override it.
protected override int GetCountCore()
{
TdCommand cmd = null;
int count = 0;
System.Diagnostics.Debug.WriteLine("begin:TDPointFeatureSource.GetCountCore " + _tableName);
// Alays be sure to wrap imporant code that accesses resources that need
// to be closed. In the Finally we will ensure they always get cleaned up.
try
{
// Here we do a standard SQL count statement and return the results.
cmd = cn.CreateCommand();
cmd.CommandText = "SELECT COUNT(*) FROM " + _tableName + _Where_wi;
cmd.Connection = cn;
count = Convert.ToInt32(cmd.ExecuteScalar());
}
finally
{
// Cleanup any of the objects that need to be closed or disposed.
if (cmd != null) { cmd.Dispose(); }
}
System.Diagnostics.Debug.WriteLine(“end:TDPointFeatureSource.GetCountCore #=” + count.ToString());
return count;
}
}
}
*************************************************************
My featureLayer:
*************************************************************
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.DesktopEdition;
using Teradata;
using Teradata.Client;
using Teradata.Client.Provider;
using System.Data.Common;
using System.Data.Odbc;
using System.Data.OleDb;
using System.Data.ProviderBase;
using System.Data.Sql;
using System.Data.SqlClient;
using System.Data.SqlTypes;
namespace GisB20
{
class TDPointFeatureLayer : FeatureLayer
{
TDPointFeatureSource tdPointFeatureSource;
// It is important for compatability that you always have a default constructor that
// takes no parameters. This constructor will just chain to the more complex one.
public TDPointFeatureLayer()
: this(string.Empty, string.Empty)
{ }
// We have provided another constructor that has all of the parameters we need for the FeatureLayer
// to work.
public TDPointFeatureLayer(string tableName, string where)
: base()
{
// Here is where we create our FeatureSource and set the internal property on the FeatureLayer
tdPointFeatureSource = new TDPointFeatureSource(tableName, where);
this.FeatureSource = tdPointFeatureSource;
}
// The next dozen lines are all of the properties we need. It is good form to always match
// the parameters in your constructors with properties of the exact same name.
}
}