Subscribe to this thread
Home - General / All posts - Cannot call expression GeocodeAddress(<dataSource>,<address>) from C# APP
BrokenDawn1 post(s)
#24-Jul-19 22:46

Hi can someone please help with my problem calling an expression in ASP.NET C# project? I'm using Visual Studio 2017 and I'm following the API document to create expression to run SQL FUNCTION GeocodeAddress(<dataSource>,<address>) and get longitude, latitude. For the data source I'm using the default GCDB in this example. Below is my code:

static void main()

{

//Application Initialize:

Manifold.Root root = new Manifold.Root(@"c:\programs\manifold-9.0.167-x64\bin64\ext.dll");

Manifold.Application app = root.Application;

//Database Config:

string tech = "datgcdb";

Manifold.PropertySet connProperties = app.CreatePropertySet();

connProperties.SetProperty("Name", "gcdb");

connProperties.SetProperty("Type", "datgcdb");

connProperties.SetProperty("Source", @"C:\manifold-8\GCDB\states.dat");

string connectionStr = connProperties.ToJson();

Manifold.Database db = app.CreateDatabase(tech, connectionStr, true);

string addr = "333 Jefferson St, San Francisco, CA, 94133";

//Run expression

Manifold.Expression expression = defineExpression(app);

Manifold.ValueSet paramSet = expression.GetSource();

paramSet[0].Data = db;

paramSet[1].Data = addr;

Manifold.ValueSet target = expression.Evaluate(paramSet);

Console.WriteLine(target[0].Data);

Console.WriteLine(target[1].Data);

}

public static Manifold.Expression defineExpression(Manifold.Application app)

{

Manifold.ValueSet source = app.CreateValueSet();

source.AddValueType("dataSource", typeof(Manifold.Database));

source.AddValueType("address", typeof(string));

return app.CreateExpressionParser().CreateExpression("GeocodeAddress(dataSource, address)", source);

}

And I got error: System.Exception: 'Invalid entity.'

There are 2 parts I'm not clear and need help:

1. In the defineExpression() method, I'm not sure if I define dataSource type correctly. I didn't find any reference about the type of dataSource, and I'm assuming it is a type of Manifold.Database, please correct me if it is wrong.

2. Not sure the standard way to pass the dataSource project in this expression, am I doing correct?

adamw


8,775 post(s)
online
#25-Jul-19 13:35

Query expressions don't take databases as parameters, they take data source objects, internally represented as tables. We are going to add means to wrap an arbitrary database into a table so that you can pass it to an expression, this is currently not in the API, but we don't need that to do what you are after, we can just create an in-memory MAP file, create a data source in that MAP file and reference that data source by name in the expression.

Here is example code for a C# console project, for x64, I took your code as a starting point and modified it, you need to modify paths to EXT.DLL and to STATES.GCDB to run it:

//C#

 

using System;

 

namespace ConsoleApp1

{

class Program

{

 

[STAThread]

static void Main(string[] args)

{

  Manifold.Root root = new Manifold.Root(

    @"c:\...\manifold-9.0.169-x64\bin64\ext.dll");

  Manifold.Application app = root.Application;

 

  // create blank MAP file to create named data source object in

  Manifold.Database db = app.CreateDatabase();

 

  // add data source object

  Manifold.PropertySet connProperties = app.CreatePropertySet();

  connProperties.SetProperty("Source", @"c:\...\states.dat");

  connProperties.SetProperty("SourceCacheExternal"false);

  string connectionStr = connProperties.ToJson();

  string datasource = db.Insert("geocoder""datasource");

  db.SetProperty(datasource, "Source", connectionStr);

  db.SetProperty(datasource, "Type""datgcdb");

 

  // create expression

  Manifold.ValueSet source = app.CreateValueSet();

  source.AddValueType("address"typeof(string));

  Manifold.ExpressionParser parser = db.CreateExpressionParser();

  string expressionText =

    string.Format("GeocodeAddress([{0}], address)", datasource);

  Manifold.Expression expression =

    parser.CreateExpression(expressionText, source);

  source = expression.GetSource();

 

  // run expression

  source[0].Data = "333 Jefferson St, San Francisco, CA, 94133";

  Manifold.ValueSet target = expression.Evaluate(source);

  Console.WriteLine(target[0].Data); // Manifold.Point<double>

  // writes: [ -122.417927142857, 37.8081546938776 ]

  //

  // can continue with:

  //   Manifold.Point<double> coord = (Manifold.Point<double>)target[0].Data;

  //   coord.X ...

  //   coord.Y ...

}

 

}

}

Quick notes:

1. The connection string does not need Name / Type, Type is a separate property and Name is not a property at all. You would probably like to turn off caching, however, because you don't need .MAPCACHE if the data source is just going to geocode - that's what SourceCacheExternal is for.

2. Since we are going to reference the data source by name, we need to create the expression parser on the database that contains that data source, not on the application. We don't need to pass it as a parameter, however.

3. GeocodeAddress returns just one value, not two. It's just that the value is FLOAT64X2, that is, it has two components: X and Y. In C# that's represented as Manifold.Point<double>, see the comment at the end of the code on how to get to X and Y.

Hope this helps.

Manifold User Community Use Agreement Copyright (C) 2007-2019 Manifold Software Limited. All rights reserved.