Skip to content

InMemoryFeatureSource

Namespace: ThinkGeo.Core

This class represents a FeatureSource backed by memory, more specifically an in memory collection InternalFeatures.

public class InMemoryFeatureSource : FeatureSource

Inheritance ObjectFeatureSourceInMemoryFeatureSource

Remarks:

You can use this kind of FeatureSource when your InternalFeatures come from an external source for which there is no FeatureSource specifically designed. An example may be real-time GPS locations. Another example might be locations that a user selected by clicking on the screen.

Properties

InternalFeatures

Gets the underlying in-memory feature collection.

public GeoCollection<Feature> InternalFeatures { get; }

Property Value

GeoCollection<Feature>
The live that stores each feature keyed by its identifier.

Remarks:

Modifying this collection bypasses the transaction system, so prefer the transactional APIs unless you explicitly need direct in-memory access.

IsEditable

Gets a value indicating whether the feature source supports editing.

public bool IsEditable { get; }

Property Value

Boolean
true if edits are allowed; otherwise, false.

Remarks:

This property is useful to check if a specific FeatureSource accepts editing. If you call the BeginTransaction and this property is false then an exception will be raised.

For developers who are creating or extending a FeatureSource it is expected that you override this virtual method if the new FeatureSource you are creating allows edits. This implementation always returns true because the data resides entirely in memory.

Id

Gets or sets the Id.

public string Id { get; }

Property Value

String

CanExecuteSqlQuery

This property specifies whether the FeatureSource can excute a SQL query or not. If it is false, then it will throw exception when these APIs are calleds: ExecuteScalar, ExecuteNonQuery, ExecuteQuery

public bool CanExecuteSqlQuery { get; }

Property Value

Boolean

Remarks:

The default implementation is false.

IsOpen

Gets a value indicating whether the feature source is currently open.

public bool IsOpen { get; }

Property Value

Boolean

Remarks:

Various methods on the FeatureSource require that it be in an open state. If one of those methods is called when the state is not open, then the method will throw an exception. To enter the open state, you must call the FeatureSource's Open method. The method will raise an exception if the current FeatureSource is already open.

Projection

Gets or sets the Projection.

public Projection Projection { get; protected set; }

Property Value

Projection

CanModifyColumnStructure

Gets or sets the CanModifyColumnStructure.

public bool CanModifyColumnStructure { get; }

Property Value

Boolean

IsInTransaction

Gets a value indicating whether the feature source currently has an active transaction.

public bool IsInTransaction { get; }

Property Value

Boolean

Remarks:

To enter a transaction, you must first call the BeginTransaction method of the FeatureSource. It is possible that some FeatureSources are read-only and do not allow edits. To end a transaction, you must either call CommitTransaction or RollbackTransaction.

IsTransactionLive

Gets or sets whether uncommitted edits are visible to queries issued against the feature source.

public bool IsTransactionLive { get; set; }

Property Value

Boolean

Remarks:

The live transaction concept means that all of the modifications you perform during a transaction are live from the standpoint of the querying methods on the object.

As an example, imagine that you have a FeatureSource that has 10 records in it. Next, you begin a transaction and then call GetAllFeatures. The result would be 10 records. After that, you call a delete on one of the records and call the GetAllFeatures again. This time you only get nine records, even though the transaction has not yet been committed. In the same sense, you could have added a new record or modified an existing one and those changes would be considered live, though not committed.
In the case where you modify records -- such as expanding the size of a polygon -- those changes are reflected as well. For example, you expand a polygon by doubling its size and then do a spatial query that would not normally return the smaller record, but instead would return the larger records. In this case, the larger records are returned. You can set this property to be false, as well; in which case, all of the spatially related methods would ignore anything that is currently in the transaction buffer waiting to be committed. In such a case, only after committing the transaction would the FeatureSource reflect the changes.

ProjectionConverter

This property holds the projection object that is used within the FeatureSource to ensure that features inside of the FeatureSource are projected.

public ProjectionConverter ProjectionConverter { get; set; }

Property Value

ProjectionConverter

Remarks:

By default this property is null, meaning that the data being passed back from any methods on the FeatureSource will be in the coordinate system of the raw data. When you specify a projection object in the property, all incoming and outgoing method calls will subject the features to projection.

For example, if the spatial database you are using has all of its data stored in decimal degrees, but you want to see the data in UTM, you would create a projection object that goes from decimal degrees to UTM and set that as the projection. With this one property set, we will ensure that it will seem to you the developer that all of the data in the FeatureSource is in UTM. That means every spatial query will return UTM projected shapes. You can even pass in UTM shapes for the parameters. Internally, we will ensure that the shapes are converted to and from the projection without any intervention on the developer's part.
In fact, even when you override virtual or abstract core methods in the FeatureSource, you will not need to know about projections at all. Simply work with the data in its native coordinate system. We will handle all of the projection at the high level method.

GeoCache

The cache system.

public FeatureCache GeoCache { get; set; }

Property Value

FeatureCache

Remarks:

You must set IsActive to true for the Cache system. The default is not active.

FeatureIdsToExclude

A collection of strings representing record id of features not to get in the Layer.

public Collection<string> FeatureIdsToExclude { get; }

Property Value

Collection<String>

Remarks:

This string collection is a handy place to specify what records not to get from the source. Suppose you have a shape file of roads and you want to hide the roads within a particular rectangle, simply execute GetFeaturesInsideBoundingBox() and add the id of the return features to the collection and forget about them. Since you can set this by Layer it makes is easy to determine what to and what not to.

TransactionBuffer

The TransactionBuffer used in the Transaction System.

public TransactionBuffer TransactionBuffer { get; set; }

Property Value

TransactionBuffer

Remarks:


The Transaction System
The transaction system of a FeatureSource sits on top of the inherited implementation of any specific source, such as Oracle Spatial or Shape files. In this way, it functions the same way for every FeatureSource. You start by calling BeginTransaction. This allocates a collection of in-memory change buffers that are used to store changes until you commit the transaction. So, for example, when you call the Add, Delete or Update method, the changes to the feature are stored in memory only. If for any reason you choose to abandon the transaction, you can call RollbackTransaction at any time and the in-memory buffer will be deleted and the changes will be lost. When you are ready to commit the transaction, you call CommitTransaction and the collections of changes are then passed to the CommitTransactionCore method and the implementer of the specific FeatureSource is responsible for integrating your changes into the underlying FeatureSource. By default the IsLiveTransaction property is set to false, which means that until you commit the changes, the FeatureSource API will not reflect any changes that are in the temporary editing buffer.
In the case where the IsLiveTransaction is set to true, then things function slightly differently. The live transaction concept means that all of the modifications you perform during a transaction are live from the standpoint of the querying methods on the object.
As an example, imagine that you have a FeatureSource that has 10 records in it. Next, you begin a transaction and then call GetAllFeatures. The result would be 10 records. After that, you call a delete on one of the records and call the GetAllFeatures again. This time you only get nine records, even though the transaction has not yet been committed. In the same sense, you could have added a new record or modified an existing one and those changes would be considered live, though not committed.
In the case where you modify records -- such as expanding the size of a polygon -- those changes are reflected as well. For example, you expand a polygon by doubling its size and then do a spatial query that would not normally return the smaller record, but instead would return the larger records. In this case, the larger records are returned. You can set this property to be false, as well; in which case, all of the spatially related methods would ignore anything that is currently in the transaction buffer waiting to be committed. In such a case, only after committing the transaction would the FeatureSource reflect the changes.

MaxRecordsToDraw

Gets or sets the MaxRecordsToDraw.

public int MaxRecordsToDraw { get; set; }

Property Value

Int32

Constructors

InMemoryFeatureSource()

Initializes a new instance of the InMemoryFeatureSource class.

public InMemoryFeatureSource()

InMemoryFeatureSource(IEnumerable<FeatureSourceColumn>)

Initializes a new instance of the InMemoryFeatureSource class.

public InMemoryFeatureSource(IEnumerable<FeatureSourceColumn> featureSourceColumns)

Parameters

featureSourceColumns IEnumerable<FeatureSourceColumn>
The columns that define the schema for the in-memory features.

Remarks:

This overload creates an empty feature source. Add columns and features after construction or call an overload that accepts seed data.

InMemoryFeatureSource(IEnumerable<FeatureSourceColumn>, IEnumerable<Feature>)

Initializes a new instance of the InMemoryFeatureSource class with predefined features.

public InMemoryFeatureSource(IEnumerable<FeatureSourceColumn> featureSourceColumns, IEnumerable<Feature> features)

Parameters

featureSourceColumns IEnumerable<FeatureSourceColumn>
The columns that define the schema for the in-memory features.

features IEnumerable<Feature>
The initial set of features to populate the source.

InMemoryFeatureSource(IEnumerable<FeatureSourceColumn>, IEnumerable<BaseShape>)

Initializes a new instance of the InMemoryFeatureSource class from shapes.

public InMemoryFeatureSource(IEnumerable<FeatureSourceColumn> featureSourceColumns, IEnumerable<BaseShape> shapes)

Parameters

featureSourceColumns IEnumerable<FeatureSourceColumn>
The columns that define the schema for the in-memory features.

shapes IEnumerable<BaseShape>
The shapes that will be wrapped in instances.

Methods

BuildIndex()

Builds a spatial index for the current in-memory features to improve spatial query performance.

public void BuildIndex()

Remarks:

Call this after directly modifying InMemoryFeatureSource.InternalFeatures so the STRtree reflects the latest shapes.

Clear()

Clears all features from the source and rebuilds the spatial index.

public void Clear()

Exceptions

InvalidOperationException
If you attempt to call this method on a feature source which is in a transaction, it will throw an InvalidOperationException.

InvalidOperationException
If you attempt to call this method on a feature source which is not opened, it will throw an InvalidOperationException.

Remarks:

The feature source must be open and not in a transaction before calling this method.

GetCountCore()

Gets the number of records currently stored in this FeatureSource.

protected long GetCountCore()

Returns

Int64
The total number of records tracked by the feature source.

Exceptions

InvalidOperationException
If the feature source is closed when this method is called, an InvalidOperationException is thrown.

Remarks:

This protected virtual method is invoked by the concrete GetCount API, so implementations do not need to handle transaction bookkeeping; the public method manages that for you.

The default implementation calls and counts the results, which is rarely efficient for larger data sets. Override this method whenever the underlying store can provide a faster count. For example, shapefiles persist the record count in their headers and spatial databases can execute optimized COUNT(*) queries without returning every feature.

CommitTransactionCore(TransactionBuffer)

This method will commit the existing transaction to its underlying source of data.

protected TransactionResult CommitTransactionCore(TransactionBuffer transactions)

Parameters

transactions TransactionBuffer
This parameter encapsulates all of the adds, edits, and deletes that make up the transaction. You will use this data to write the changes to your underlying data source.

Returns

TransactionResult

        A  describing how many operations succeeded or failed and
        any errors that occurred while committing the transaction.

Exceptions

InvalidOperationException
In the event you attempt to call this method on a feature source which is not in transaction it will throw an InvalidOperationException.

Remarks:

This method commits the pending operations found in the transaction buffer to the underlying data store and returns a TransactionResult so callers can inspect any failures. The base class handles transaction life-cycle management, so derived classes only need to persist the operations they receive. The Transaction System FeatureSource transactions collect changes in in-memory buffers that are allocated when is called. Add, Delete, and Update operations are queued until you either call or . During commit the buffers are passed to this method so the concrete feature source can write the edits to its store. The IsLiveTransaction property controls whether pending edits are visible to query methods. By default the property is false, so pending edits remain invisible until the commit completes. When set to true the in-memory buffers are treated as live data. For example, deleting one record from a set of ten while in a live transaction causes subsequent calls to GetAllFeatures to return nine features even before the transaction is committed. Spatial changes, such as expanding a polygon, are likewise reflected in spatial queries.

GetAllFeaturesCore(IEnumerable<String>)

This method returns all of the InternalFeatures in the FeatureSource.

protected Collection<Feature> GetAllFeaturesCore(IEnumerable<string> returningColumnNames)

Parameters

returningColumnNames IEnumerable<String>
This parameter allows you to select the field names of the column data you wish to return with each Feature.

Returns

Collection<Feature>

        A collection containing every feature currently stored in the source.

Exceptions

InvalidOperationException
In the event you attempt to call this method on a feature source which has not been opened it will throw an InvalidOperationException.

Remarks:

This method returns all of the InternalFeatures in the FeatureSource. You will not need to consider anything about pending transactions as this will be handled in the non Core version of the method.

The main purpose of this method is to be the anchor of all of our default virtual implementations within this class. We wanted as the framework developers to provide you the user with as much default virtual implementation as possible. To do this we needed a way to get access to all of the features. For example, we want to create a default implementation for finding all of the InternalFeatures in a bounding box. Because this is an abstract class we do not know the specifics of the underlying data or how its spatial indexes work. What we do know is that if we get all the records then we can brute force the answer. In this way if you inherit from this class and only implement this one method we can provide default implementations for virtually every other API.
While this is nice for you the developer if you decide to create your own FeatureSource it comes with a price. The price is that it is very inefficient. In the case we just discussed about finding all of the InternalFeatures in a bounding box we would not want to look at every record to fulfill this method. Instead we would want to override the GetFeaturesInsideBoundingBoxCore and implement specific code that would be fast. For example in Oracle Spatial there is a specific SQL statement to do this operation very quickly. The same holds true with other specific FeatureSource examples.
Most default implementations in the FeatureSource call the GetFeaturesInsideBoundingBoxCore which by default calls the GetAllFeaturesCore. It is our advice that if you create your own FeatureSource that you ALWAYS override the GetFeaturesInsideBoundingBox. It will ensure that nearly every other API will operate efficiently. Please see the specific API to determine what method it uses.

GetAllFeaturesCore(IEnumerable<String>, Int32, Int32)

Returns a subset of in-memory features starting at the specified index.

protected Collection<Feature> GetAllFeaturesCore(IEnumerable<string> returningColumnNames, int startIndex, int takeCount)

Parameters

returningColumnNames IEnumerable<String>
The field names whose column values should be populated on the returned features.

startIndex Int32
Zero-based index of the first feature to include in the result.

takeCount Int32
Maximum number of features to return.

Returns

Collection<Feature>
A collection that contains at most features beginning at .

Remarks:

This overload exists to support paging scenarios when callers only need a limited window of the dataset.

GetFeaturesInsideBoundingBoxCore(RectangleShape, IEnumerable<String>)

This method returns all of the InternalFeatures of this FeatureSource that are inside of the specified bounding box.

protected Collection<Feature> GetFeaturesInsideBoundingBoxCore(RectangleShape boundingBox, IEnumerable<string> returningColumnNames)

Parameters

boundingBox RectangleShape
This parameter represents the bounding box that you wish to find InternalFeatures inside of.

returningColumnNames IEnumerable<String>
This parameter allows you to select the field names of the column data that you wish to return with each Feature. If you pass a null as the returningColumnNames, we will throw an ArgumentNullException.If you pass a null as the boundingBox, we will throw an ArgumentNullException.

Returns

Collection<Feature>
A collection of features contained within the specified bounding box.

Exceptions

InvalidOperationException
In the event you attempt to call this method on a feature source which has not been opened, it will throw an InvalidOperationException.

Remarks:

specified bounding box. If you are overriding this method you will not need to consider anything about transactions, as this is handled by the concrete version of this method.

The default implementation of GetFeaturesInsideBoundingBoxCore uses the GetAllFeaturesCore method to determine which InternalFeatures are inside of the bounding box. We strongly recommend that you provide your own implementation for this method that will be more efficient. That is especially important for this method, as many other default virtual methods use this for their calculations. When you override this method, we highly recommend that you use any spatial indexes you have at your disposal to make this method as fast as possible.

GetFeaturesInsideBoundingBoxByReference(RectangleShape, IEnumerable<String>)

internal Collection<Feature> GetFeaturesInsideBoundingBoxByReference(RectangleShape boundingBox, IEnumerable<string> returningColumnNames)

Parameters

boundingBox RectangleShape

returningColumnNames IEnumerable<String>

Returns

Collection<Feature>

GetFeaturesOutsideBoundingBoxCore(RectangleShape, IEnumerable<String>)

Gets all features that fall outside the specified bounding box.

protected Collection<Feature> GetFeaturesOutsideBoundingBoxCore(RectangleShape boundingBox, IEnumerable<string> returningColumnNames)

Parameters

boundingBox RectangleShape
This parameter represents the bounding box that you wish to find InternalFeatures outside of.

returningColumnNames IEnumerable<String>
This parameter allows you to select the field names of the column data you wish to return with each Feature. If you pass a null as the returningColumnNames, we will throw an ArgumentNullException.If you pass a null as the boundingBox, we will throw an ArgumentNullException.

Returns

Collection<Feature>
A collection containing every feature that is not entirely contained within the bounding box.

Exceptions

InvalidOperationException
In the event you attempt to call this method on a feature source which has not been opened, it will throw an InvalidOperationException.

Remarks:

If the current transaction is open and live, the pending edits are also evaluated by this method. The default implementation uses and filters the results, so overriding it with source-specific spatial logic is strongly recommended for production scenarios.

GetColumnsCore()

This method returns the columns available for the FeatureSource.

protected Collection<FeatureSourceColumn> GetColumnsCore()

Returns

Collection<FeatureSourceColumn>
This method returns the columns available for the FeatureSource.

Exceptions

InvalidOperationException
In the event you attempt to call this method on a feature source which has not been opened it will throw an InvalidOperationException.

Remarks:

When overriding you will be responsible for getting a list of all of the columns supported by the FeatureSource. In this way the FeatureSource will know what columns are available and will remove any extra columns when making calls to other core methods. For example if you have a FeatureSource that has three columns of information and the user calls a method and requests four columns of information, something they can do with custom fields, we will first compare what they are asking for to the results of the GetColumnsCore. In this way we can strip out custom columns before calling other Core methods which are only responsible for returning data in the FeatureSource. For more information on custom fields you can see the documentation on the OnCustomFieldsFetch.

Events

DrawingProgressChanged

Occurs when the DrawingProgressChanged event is raised.

public event EventHandler<DrawingProgressChangedEventArgs> DrawingProgressChanged;

GettingColumns

Occurs when the GettingColumns event is raised.

public event EventHandler<GettingColumnsFeatureSourceEventArgs> GettingColumns;

GottenColumns

Occurs when the GottenColumns event is raised.

public event EventHandler<GottenColumnsFeatureSourceEventArgs> GottenColumns;

GettingFeaturesByIds

Occurs when the GettingFeaturesByIds event is raised.

public event EventHandler<GettingFeaturesByIdsFeatureSourceEventArgs> GettingFeaturesByIds;

GettingFeaturesForDrawing

Occurs when the GettingFeaturesForDrawing event is raised.

public event EventHandler<GettingFeaturesForDrawingFeatureSourceEventArgs> GettingFeaturesForDrawing;

CustomColumnFetch

This event is raised when fields are requested in a feature source method that do not exist in the feature source. It allows you to supplement the data from any outside source you have.

public event EventHandler<CustomColumnFetchEventArgs> CustomColumnFetch;

Remarks:

source you have.

It is used primarily when you have data relating to a particular feature or set of features that is not within source of the data. For example, you may have a shape file of the world whose .dbf component describes the area and population of each country. Additionally, in an outside SQL Server table, you may also have data about the countries, and it is this data that you wish to use for determining how you want to color each country.
To integrate this SQL data, you simply create a file name that does not exist in the .dbf file. Whenever Map Suite is queried to return records that specifically require this field, the FeatureSource will raise this event and allow you the developer to supply the data. In this way, you can query the SQL table and store the data in some sort of collection, and then when the event is raised, simply supply that data.
As this is an event, it will raise for each feature and field combination requested. This means that the event can be raised quite often, and we suggest that you cache the data you wish to supply in memory. We recommend against sending out a new SQL query each time this event is raised. Image that you are supplementing two columns and your query returns 2,000 rows. This means that if you requested those fields, the event would be raised 4,000 times.

CommittingTransaction

This event is raised after the CommitTransaction method is called, but before the CommitTransactionCore is called. This allows you access to the TransactionBuffer before the transaction is committed. It also allows you to cancel the pending commit of the transaction.

public event EventHandler<CommittingTransactionEventArgs> CommittingTransaction;

Remarks:

This event is raised before the CommitTransactionCore is called and allows you access to the TransactionBuffer before the transaction is committed. It also allows you to cancel the pending transaction. The TransactionBuffer is the object that stores all of the pending transactions and is accessible through this event to allow you to either add, remove or modify transactions.

In the event that you cancel the CommitTransaction method, the transaction remains intact and you will still be editing. This makes it a nice place to possibly check for connectivity before the TransactionCore code is run, which is where the records are actually committed. Calling the RollBackTransaction method is the only way to permanently cancel a pending transaction without committing it.

CommittedTransaction

This event is raised after the CommitTransaction and the CommitTransactionCore are called and allows you access to the TransactionBuffer and the TransactionResults object before CommitTransaction method is returned.

public event EventHandler<CommittedTransactionEventArgs> CommittedTransaction;

Remarks:

This event is raised after the CommitTransactionCore is called and allows you access to the TransactionBuffer and the TransactionResults object before CommitTransaction method is returned.

With this event, you can analyse the results of the transaction and do any cleanup code necessary. In the event some of the records did not commit, you can handle those items here. The TransactionResults object is passed out of the CommitTransaction method so you could analyze it then; however, this is the only place where you have access to both the TransactionResults object and the TransactionBuffer object at the same time. These are useful together to try and determine what went wrong and possibly try and re-commit them.
At the time of this event you will technically be out of the current transaction.

OpeningFeatureSource

This event is called before the opening of the FeatureSource.

public event EventHandler<OpeningFeatureSourceEventArgs> OpeningFeatureSource;

Remarks:

This event is called before the opening of the FeatureSource. Technically, this event is called after the calling of the Open method on the FeatureSource, but before the protected OpenCore method.

It is typical that the FeatureSource may be opened and closed may times during the life cycle of your application. The type of control the MapEngine is embedded in will dictate how often this happens. For example, in the case of the Web Edition, each time a FeatureSource is in the Ajax or Post Back part of the page cycle, it will close the FeatureSource before returning back to the client. This is to conserve resources, as the web is a connection-less environment. In the case of the Desktop Edition, we can keep the FeaureSources open, knowing that we can maintain a persistent connection.

OpenedFeatureSource

This event is called after the opening of the FeatureSource.

public event EventHandler<OpenedFeatureSourceEventArgs> OpenedFeatureSource;

Remarks:

This event is called after the opening of the FeatureSource. Technically, this event is called after the calling of the Open method on the FeatureSource and after the protected OpenCore method is called.

It is typical that the FeatureSource may be opened and closed may times during the life cycle of your application. The type of control the MapEngine is embedded in will dictate how often this happens. For example, in the case of the Web Edition, each time a FeatureSource is in the Ajax or Post Back part of the page cycle, it will close the FeatureSource before returning back to the client. This is to conserve resources, as the web is a connection-less environment. In the case of the Desktop Edition, we can keep the FeaureSources open, knowing that we can maintain a persistent connection.

ClosingFeatureSource

This event is called before the closing of the FeatureSource.

public event EventHandler<ClosingFeatureSourceEventArgs> ClosingFeatureSource;

Remarks:

This event is called before the closing of the FeatureSource. Technically, this event is called after the calling of the Close method on the FeatureSource, but before the protected CloseCore method.

It is typical that the FeatureSource may be opened and closed may times during the life cycle of your application. The type of control the MapEngine is embedded in will dictate how often this happens. For example, in the case of the Web Edition, each time a FeatureSource is in the Ajax or Post Back part of the page cycle, it will close the FeatureSource before returning back to the client. This is to conserve resources, as the web is a connection-less environment. In the case of the Desktop Edition, we can keep the FeaureSources open, knowing that we can maintain a persistent connection.

ClosedFeatureSource

This event is called after the closing of the FeatureSource.

public event EventHandler<ClosedFeatureSourceEventArgs> ClosedFeatureSource;

Remarks:

This event is called after the closing of the FeatureSource. Technically, this event is called after the calling of the Close method on the FeatureSource and after the protected CloseCore method.

It is typical that the FeatureSource may be opened and closed may times during the life cycle of your application. The type of control the MapEngine is embedded in will dictate how often this happens. For example, in the case of the Web Edition, each time a FeatureSource is in the Ajax or Post Back part of the page cycle, it will close the FeatureSource before returning back to the client. This is to conserve resources, as the web is a connection-less environment. In the case of the Desktop Edition, we can keep the FeaureSources open, knowing that we can maintain a persistent connection.