Quick Start Using Massive and PostGreSQL

Most of the documentation for using Massive is OK – there are one or two things you might need to be aware of when you start a project from scratch – and I mean from scratch.  Follow these steps and you shouldn’t go far wrong.


OK – so I have a PostgreSQL database installed (called “geodb”) and I have table called Report.

report table

As you can see it’s just some basic text and ids, nothing special here.

I create a new Windows application using Visual Studio, it could be a console app – it’s not important – just something to get you started.

Install Npgsql

You will need to have the Npgsql installed/referenced into your project, so you can at least “talk” to the database, and Massive needs this to be able to do this.  In the Package Manager Console just type (bear in mind the version will probably be different when you read this):

PM> Install-Package Npgsql -Version 3.0.4


Modify App.config

This is always mentioned – but you do have to modify you App.config for you project.  This is so Massive can find your database connection string and it knows which dll to load in to talk to the database – which is the Npgsql.dll in this case.


Your App.Config should look like this:


The connection string goodness and DbProviderFactories section detailing the dll – make sure the Version tallies up with the one in your project – just get the properties of the dll from the References treeview in the project.


Create Massive Class

Quite easy to do – you can add Massive by Nuget, or just copy paste the code from GitHub for the PostgreSQL version and make a new class file.

Create Report Class

Create a new class – inheriting DynamicModel, passing in the name of database, the table and the primary key.

public class Report: DynamicModel
    public Report() : base("geodb", "report", "id")


Test Code

Make an instance of the class by copying the code below:

var table = new Report();
foreach (var rec in table.All())
     / /These apply to the column names.
     Console.WriteLine("{0} {1} ", rec.id, rec.name);


Put the code in a Main() method or button click event to just test the code and it should just all work fairy easily.

Quick Start Using Massive and PostGreSQL

Find all layers of a type recursively in ArcMap

This code snippit will allow you to return all layers of a type you specify from an mxd.  Very handy code:

public List<ILayer> LoopThroughLayersOfSpecificUID(IMap map, String layerCLSID, bool searchRecursive)
/// The different layer GUID's and Interface's are:
/// "{AD88322D-533D-4E36-A5C9-1B109AF7A346}" = IACFeatureLayer
/// "{74E45211-DFE6-11D3-9FF7-00C04F6BC6A5}" = IACLayer
/// "{495C0E2C-D51D-4ED4-9FC1-FA04AB93568D}" = IACImageLayer
/// "{65BD02AC-1CAD-462A-A524-3F17E9D85432}" = IACAcetateLayer
/// "{4AEDC069-B599-424B-A374-49602ABAD308}" = IAnnotationLayer
/// "{DBCA59AC-6771-4408-8F48-C7D53389440C}" = IAnnotationSublayer
/// "{E299ADBC-A5C3-11D2-9B10-00C04FA33299}" = ICadLayer
/// "{7F1AB670-5CA9-44D1-B42D-12AA868FC757}" = ICadastralFabricLayer
/// "{BA119BC4-939A-11D2-A2F4-080009B6F22B}" = ICompositeLayer
/// "{9646BB82-9512-11D2-A2F6-080009B6F22B}" = ICompositeGraphicsLayer
/// "{0C22A4C7-DAFD-11D2-9F46-00C04F6BC78E}" = ICoverageAnnotationLayer
/// "{6CA416B1-E160-11D2-9F4E-00C04F6BC78E}" = IDataLayer
/// "{0737082E-958E-11D4-80ED-00C04F601565}" = IDimensionLayer
/// "{48E56B3F-EC3A-11D2-9F5C-00C04F6BC6A5}" = IFDOGraphicsLayer
/// "{40A9E885-5533-11D0-98BE-00805F7CED21}" = IFeatureLayer
/// "{605BC37A-15E9-40A0-90FB-DE4CC376838C}" = IGdbRasterCatalogLayer
/// "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}" = IGeoFeatureLayer
/// "{34B2EF81-F4AC-11D1-A245-080009B6F22B}" = IGraphicsLayer
/// "{EDAD6644-1810-11D1-86AE-0000F8751720}" = IGroupLayer
/// "{D090AA89-C2F1-11D3-9FEF-00C04F6BC6A5}" = IIMSSubLayer
/// "{DC8505FF-D521-11D3-9FF4-00C04F6BC6A5}" = IIMAMapLayer
/// "{34C20002-4D3C-11D0-92D8-00805F7C28B0}" = ILayer
/// "{E9B56157-7EB7-4DB3-9958-AFBF3B5E1470}" = IMapServerLayer
/// "{B059B902-5C7A-4287-982E-EF0BC77C6AAB}" = IMapServerSublayer
/// "{82870538-E09E-42C0-9228-CBCB244B91BA}" = INetworkLayer
/// "{D02371C7-35F7-11D2-B1F2-00C04F8EDEFF}" = IRasterLayer
/// "{AF9930F0-F61E-11D3-8D6C-00C04F5B87B2}" = IRasterCatalogLayer
/// "{FCEFF094-8E6A-4972-9BB4-429C71B07289}" = ITemporaryLayer
/// "{5A0F220D-614F-4C72-AFF2-7EA0BE2C8513}" = ITerrainLayer
/// "{FE308F36-BDCA-11D1-A523-0000F8774F0F}" = ITinLayer
/// "{FB6337E3-610A-4BC2-9142-760D954C22EB}" = ITopologyLayer
/// "{005F592A-327B-44A4-AEEB-409D2F866F47}" = IWMSLayer
/// "{D43D9A73-FF6C-4A19-B36A-D7ECBE61962A}" = IWMSGroupLayer
/// "{8C19B114-1168-41A3-9E14-FC30CA5A4E9D}" = IWMSMapLayer

List<ILayer> layers = new List<ILayer>();

if (map == null || layerCLSID == null)
return layers;

ESRI.ArcGIS.esriSystem.IUID uid = new ESRI.ArcGIS.esriSystem.UIDClass();
uid.Value = layerCLSID; // Example: "{E156D7E5-22AF-11D3-9F99-00C04F6BC78E}" = IGeoFeatureLayer
IEnumLayer enumLayer = map.get_Layers(((ESRI.ArcGIS.esriSystem.UID)(uid)), searchRecursive); // Explicit Cast
ILayer layer = enumLayer.Next();

while (!(layer == null))
layer = enumLayer.Next();
catch (System.Exception ex)
MessageBox.Show("No layers of type: " + uid.Value.ToString() + " " + ex.Message);
return layers;


Find all layers of a type recursively in ArcMap

Deleting corrupt rasters from ArcSDE

Sometimes data gets corrupted when trying to load data into ArcSDE.  This can be problematic as standard and recommended processes to remove data from ArcSDE cannot be used (i.e. ArcCatalog).

Manual deletion must be undertaken by going to the database directly and deleting all record of the data in the SDE system tables and the actual business table itself.  Yes, this is scary!, but if you do some defensive SQL to create “backups” of the data you are about to delete then you should be OK.  Also check that you have made a backup of your database too for “belt and braces”.

Featured image

In SDE Schema:

SELECT rastercolumn_id FROM raster_columns WHERE table_name = <table name>
SELECT layer_id FROM layers WHERE table_name = <table name>

The results from above will be used in the schema where the faulty raster is stored so make a note of the rastercolumn_id and the layer_id  !!

CREATE TABLE table_registry_bak AS SELECT * FROM table_registry WHERE table_name = <table name>;
DELETE FROM table_registry WHERE table_name = <table name>;

CREATE TABLE layers_bak AS SELECT * FROM layers WHERE table_name = <table name>;
DELETE FROM layers WHERE table_name = <table name>;

CREATE TABLE raster_columns_bak AS SELECT * FROM raster_columns WHERE table_name = <table name>;
DELETE FROM raster_columns WHERE table_name = <table name>;

CREATE TABLE gdb_objectclasses_bak AS SELECT * FROM gdb_objectclasses WHERE NAME = <table name>;
DELETE FROM gdb_objectclasses WHERE NAME = <table name>;

CREATE TABLE geometry_columns_bak AS SELECT * FROM geometry_columns WHERE f_table_name = <table name>;
DELETE FROM geometry_columns WHERE f_table_name = <table name>;

CREATE TABLE column_registry_bak AS SELECT * FROM column_registry WHERE table_name = <table name>;
DELETE FROM column_registry WHERE table_name = <table name>;

In the faulty data schema:

CREATE TABLE DEM_20M_0042_LUTE_ON_SP_HS_bak AS SELECT * FROM <table name>;
DROP TABLE <table name>;

CREATE TABLE sde_aux_<rastercolumn_id>_bak AS SELECT * FROM sde_aux_<rastercolumn_id>;
DROP TABLE sde_aux_<rastercolumn_id>;

CREATE TABLE sde_bnd_<rastercolumn_id>_bak AS SELECT * FROM sde_bnd_<rastercolumn_id>;
DROP TABLE sde_bnd_<rastercolumn_id>;

CREATE TABLE sde_blk_<rastercolumn_id>_bak AS SELECT * FROM sde_blk_<rastercolumn_id>;
DROP TABLE sde_blk_<rastercolumn_id>;

CREATE TABLE sde_ras_<rastercolumn_id>_bak AS SELECT * FROM sde_ras_<rastercolumn_id>;
DROP TABLE sde_ras_<rastercolumn_id>;

CREATE TABLE f4707_bak AS SELECT * FROM f<layer_id> ;
DROP TABLE f<layer_id>;

CREATE TABLE s<layer_id>_bak AS SELECT * FROM s<layer_id>;
DROP TABLE s<layer_id>;

Once you have run these sql commands, check everything is ok in ArcCatalog, then delete all tables with “_bak” to clean everything up.

Deleting corrupt rasters from ArcSDE

Simple Interface Example in C#

The following shows a simple example of how Interfaces can be very useful in C#.  Here SomeOtherClass doesn’t care what’s passed in as long as it conforms to ILog, then it will be able to call the Log function – this is truly polymorphic guys!


public interface ILog
 void Log(string text);
public class FileLog : ILog
 public void Log(string text)
  // write text to a file
public class DatabaseLog : ILog
 public void Log(string text)
  // write text to the database
public class SomeOtherClass
 private ILog _logger;
 public SomeOtherClass(ILog logger)
  // I don't know if logger is the FileLog or DatabaseLog
  // but I don't need to know either as long as its implementing ILog
  this._logger = logger;
  logger.Log("Hello World!");
Simple Interface Example in C#

Sublime Text 2 – Open Chrome Tab on Build

Simple to create automatically open a Chrome tab when editing HTML and wanting to see your changes.

  1. Select New Build System from the menus – see below:


2.  Get rid of the default text and replace with where you have installed the Google Chrome executable – it should look something like this (be sure to put in double backslashes for the filepath and put in “$file” after the filepath too:


3.  Save it as something sensible like “Chrome”.

4.  Then in the Build System menu (see first screenshot), you should see “Chrome” appear, select this.  Now press Ctrl+B or select Build from the Tools menu and it should open a new tab in Chrome.

Pretty easy.

Sublime Text 2 – Open Chrome Tab on Build

Custom Component Depoloyment (ESRI) – better to use TARGETDIR

I think ESRI may be wrong on how to properly set up a custom installer for your custom dll’s for ArcMap etc.

How to deploy a custom component using a setup project


custom install


It’s basically implying that you should use:


Which translates to soemthing like “C:\Program Files(x86)\MyCompany\bin\foo.dll”

But this may not always be true, what happens when your user wants to install to a custom installation directory?  The ESRIRegAsm.exe tool will always fire against – C:\Program Files(x86)\MyCompany\bin\foo.dll, and not where the user selected to install! – it’s basically hard wired so that means your customers could have problems trying to install your software.  It’s better to use:


Which is basically the value you get back from this stage in the installation process (although it’s not very clear as you don’t see that as a variable in the properties window for this stage!):

install folder


This will then run ESRIRegAsm.exe against where the user decided to install your dll’s, properly installing the dlls into ArcMap etc.  This is, I believe more foolproof.  However if I have got this wrong, I’m happy to be proved wrong 🙂

Custom Component Depoloyment (ESRI) – better to use TARGETDIR