[{"data":1,"prerenderedAt":58},["ShallowReactive",2],{"blog-post-working-with-file-geodatabase-in-csharp-1":3,"blog-sidebar-tags":40,"blog-sidebar-popular":45},{"overview":4,"post":29},{"slug":5,"title":6,"subtitle":7,"opener":8,"tags":9,"date":12,"headerImage":13,"author":18,"images":7,"__typename":28},"working-with-file-geodatabase-in-csharp-1","Working with File Geodatabase using GDAL\u002FOGR in C# - Part 1",null,"The first part of this blog series is providing some background information and lays the basis for working with the ESRI File Geodatabase data format for geospatial data.",[10,11],"Geo","C#","2020-08-05T00:00:00Z",[14],{"fileName":15,"url":16,"__typename":17},"gdb-ua2012.png","https:\u002F\u002Fcms.spatial-focus.net\u002Fapi\u002Fassets\u002Fspatialfocus\u002Fd99f43f5-59a9-42e3-bafa-20901048c80c\u002F","Asset",[19],{"id":20,"flatData":21,"__typename":27},"247edfce-2ecf-40b8-87e1-58e549d0c243",{"name":22,"image":23,"__typename":26},"Christoph Perger",[24],{"url":25,"__typename":17},"https:\u002F\u002Fcms.spatial-focus.net\u002Fapi\u002Fassets\u002Fspatialfocus\u002F967c15d7-bd4a-4d6e-9e34-b891dccb9906\u002F","AuthorFlatDataDto","Author","PostsFlatDataDto",{"slug":5,"title":6,"subtitle":7,"headerImage":30,"opener":8,"text":32,"tags":33,"date":12,"repo":34,"author":35,"images":7,"__typename":28},[31],{"fileName":15,"url":16,"__typename":17},"# About\n\nWorking with geospatial data can be tricky without proper tools and guidelines. Years ago we have been working on a project with the task to analyze and handle raster and vector datasets. Back then the only supported vector-format was ESRI Shapefile, so the .NET library DotSpatial looked quite promising and was working well until now. However this package was not updated in the last few years, also new requirements like .NET Core, potentially Linux support and File Geodatabase support required some rethinking.\n\nWe are focussing now on the File Geodatabase support here. File Geodatabase is data format developed by [ESRI](https:\u002F\u002Fwww.esri.com\u002F) and more or less replaces the older Personal Geodatabase format, based on Microsoft Access. It is a container format for storing both vector as well as raster data. Typically this format is represented as a folder with the .gdb suffix, but it can also be compressed in a zip-archive.\n\n# Walkthrough\n\nThis tutorial series is split into 3 separate posts and gives you some insights into how to handle File Geodatabase in your C# solutions. \n\n- Part 1: Getting started, opening and examining the File Geodatabase\n- Part 2: [Analyzing the data and building indexes for later use](\u002Fblog\u002Fworking-with-file-geodatabase-in-csharp-2)\n- Part 3: [Sampling data from the File Geodatabase](\u002Fblog\u002Fworking-with-file-geodatabase-in-csharp-3)\n\n__Note:__ As test data for the following examples, we are using the [Urban Atlas 2012](https:\u002F\u002Fland.copernicus.eu\u002Flocal\u002Furban-atlas\u002Furban-atlas-2012) for Austria, which you also find in the sample code of this blog post. Any sceenshots or output we are showing here will visualize the output of this particular file geodatabase, but the results should look very similar for any other dataset as well.\n\n# Related tools\n\n## GDAL\u002FOGR\n\nGDAL\u002FOGR is the de-facto standard open source libary for reading and writing geospatial data formats. The [Geospatial Data Abstraction Library (GDAL)](https:\u002F\u002Fwww.osgeo.org\u002Fprojects\u002Fgdal\u002F) is split into 3 main components:\n\n- GDAL - for raster data formats\n- OGR - for vector data formats\n- PROJ - for projections and transformations\n\n## .NET Core bindings\n\nGDAL is written in C, so we need a wrapper to use it in our .NET application. Searching for NuGet packages results in two potential solutions:\n\n- [Gdal.Core](https:\u002F\u002Fwww.nuget.org\u002Fpackages\u002FGdal.Core) from jgoday which is using GDAL 2.3 and wasn't updated in the last 18 months\n- [MaxRev.Gdal.Core](https:\u002F\u002Fwww.nuget.org\u002Fpackages\u002FMaxRev.Gdal.Core) from MaxRev that is using the quite recent GDAL 3.0.1 and maintains the active [Github repo gdal.netcore](https:\u002F\u002Fgithub.com\u002FMaxRev-Dev\u002Fgdal.netcore), which is why we choose it for our purpose\n\n# Installation & Setup\n\nWe start with a new .NET Core Console App and install the Gdal.Core NuGet Packages (select the runtime based on your target OS):\n\n```\ndotnet add package MaxRev.Gdal.Core\ndotnet add package MaxRev.Gdal.WindowsRuntime.Minimal\n```\n\nNext step is to add the using statement and run the ConfigureAll method:\n\n```csharp\nnamespace FileGeodatabaseSample\n{\n    using MaxRev.Gdal.Core;\n\n    public class Program\n    {\n        public static void Main(string[] args)\n        {\n            GdalBase.ConfigureAll();\n\n            \u002F\u002F GDAL is ready.\n        }\n    }\n}\n```\n\n# Opening and examining the File Geodatabase\n\nIn the following chapters we are going to perform a few common tasks when handling file geodatabases, starting from simply opening and examining its content over more in-depth analysis regarding individual layers, attributes and geometric properties to a number of specific and applied tasks.\n\n## Open\n\nTo open a file geodatabase we have to select the appropriate *OGR driver*. There are two options:\n\n- the [OpenFileGDB driver](https:\u002F\u002Fgdal.org\u002Fdrivers\u002Fvector\u002Fopenfilegdb.html), which is built into OGR by default but supports __only read access__\n- the [ESRI FileGDB driver](https:\u002F\u002Fgdal.org\u002Fdrivers\u002Fvector\u002Ffilegdb.html), which requires the additional FileGDB API library, hence requires some more preparatory work but supports also editing of data\n\nSince we are only reading and analyzing data in this post we will go with the simpler, built-in option and leave the latter option for a potential future blog post.\n\nAfter we selected the right driver, we can simply open the GDB. __Note:__ There is no need to extract the zipped geodatabase. The driver works with both the zipped or unzipped version.\n\nAfter that we can iterate over the contained layers and print their names in the console.\n\n```csharp\nprivate static void Open(string dataSetPath)\n{\n    var fileGdbDriver = Ogr.GetDriverByName(\"OpenFileGDB\");\n    var dataSource = fileGdbDriver.Open(dataSetPath, 0);\n\n    var layerCount = dataSource.GetLayerCount();\n\n    for (var i = 0; i \u003C layerCount; i++)\n    {\n        var layer = dataSource.GetLayerByIndex(i);\n\n        Console.WriteLine($\"Layer: {layer.GetName()}\");\n    }\n}\n```\n\nIn our case the ouput will look like this:\n\n```\nLayer: UA2012_AT_Merge\n```\n\n## Layer details\n\nNow that we opened the file geodatabase and successfully identified the contained layers, we can have a closer look at the layer. In the following example we will:\n\n- identify the shape type (e.g. Point, Line, Polygon, Multi-*)\n- get its spatial properties (projection and dataset extent)\n- get the total number of features\n- and the attributes (name and type)\n\n```csharp\nprivate static void Details(string dataSetPath)\n{\n    var fileGdbDriver = Ogr.GetDriverByName(\"OpenFileGDB\");\n    var dataSource = fileGdbDriver.Open(dataSetPath, 0);\n    var layer = dataSource.GetLayerByIndex(0);\n\n    var shapeType = layer.GetGeomType().ToString(\"G\").Substring(3);\n    Console.WriteLine($\"Shape Type: {shapeType}\");\n\n    var spatialReference = layer.GetSpatialRef();\n    var projectionName = spatialReference.GetName();\n    Console.WriteLine($\"Projection: {projectionName}\");\n\n    var extent = new Envelope();\n    layer.GetExtent(extent, 0);\n    var dataSetExtent = new\n    {\n        XMin = extent.MinX,\n        XMax = extent.MaxX,\n        YMin = extent.MinY,\n        YMax = extent.MaxY,\n    };\n\n    Console.WriteLine($\"Extent: {JsonSerializer.Serialize(dataSetExtent, new JsonSerializerOptions { WriteIndented = true })}\");\n\n    var featureCount = (int)layer.GetFeatureCount(0);\n    Console.WriteLine($\"Feature Count: {featureCount}\");\n\n    var columns = new List\u003Cdynamic>();\n\n    var layerDefinition = layer.GetLayerDefn();\n    for (var j = 0; j \u003C layerDefinition.GetFieldCount(); j++)\n    {\n        var field = layerDefinition.GetFieldDefn(j);\n        columns.Add(new\n        {\n            Name = field.GetName(),\n            DataType = field.GetFieldTypeName(field.GetFieldType()),\n        });\n    }\n\n    Console.WriteLine($\"Columns: {JsonSerializer.Serialize(columns, new JsonSerializerOptions { WriteIndented = true })}\");\n}\n```\n\nOutput:\n\n```\nShape Type: MultiPolygon\nProjection: ETRS89 \u002F LAEA Europe\nExtent: {\n  \"XMin\": 4382010.8362,\n  \"XMax\": 4854633.2937,\n  \"YMin\": 2595132.8378,\n  \"YMax\": 2879685.3701\n}\nFeature Count: 304122\nColumns: [\n  {\n    \"Name\": \"COUNTRY\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"CITIES\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"FUA_OR_CIT\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"CODE2012\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"ITEM2012\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"PROD_DATE\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"IDENT\",\n    \"DataType\": \"String\"\n  },\n  {\n    \"Name\": \"Shape_Leng\",\n    \"DataType\": \"Real\"\n  },\n  {\n    \"Name\": \"Shape_Length\",\n    \"DataType\": \"Real\"\n  },\n  {\n    \"Name\": \"Shape_Area\",\n    \"DataType\": \"Real\"\n  }\n]\n```\n\n# Next steps\n\nSince we are now able to open a File Geodatabase, iterate over its layers and extract some metadata, it is time to look at the actual data in the layer. This will be done in [part 2](\u002Fblog\u002Fworking-with-file-geodatabase-in-csharp-2) of our series.",[10,11],"https:\u002F\u002Fgithub.com\u002FSpatialFocus\u002Fsample-working-with-file-geodatabase-in-csharp",[36],{"id":20,"flatData":37,"__typename":27},{"name":22,"image":38,"__typename":26},[39],{"url":25,"__typename":17},[11,41,42,43,10,44],"DDD","EF","Clean code","web",[46,52],{"slug":47,"title":48,"headerImage":49,"__typename":28},"radial-progress-css-animation","Radial progress with CSS",[50],{"url":51,"__typename":17},"https:\u002F\u002Fcms.spatial-focus.net\u002Fapi\u002Fassets\u002Fspatialfocus\u002Fb7cdc0ef-364e-4444-8dd3-b85f19e87820\u002F",{"slug":53,"title":54,"headerImage":55,"__typename":28},"load-testing-put-endpoints-with-apache-jmeter","Load testing PUT endpoints",[56],{"url":57,"__typename":17},"https:\u002F\u002Fcms.spatial-focus.net\u002Fapi\u002Fassets\u002Fspatialfocus\u002Fad44fc84-935c-4ab4-ab0e-9fbcb84fb2c1\u002F",1783525747615]