cancel
Showing results for 
Search instead for 
Did you mean: 

Join the community at Nodes 2022, our free virtual event on November 16 - 17.

Neo4J.Client remote connection fails

lucas_gadiel
Node Link

Hello

I am new to Neo4J and graph DB
also not a pro in C#

i get to do the connection in a remote server easy and run my query.
using Neo4j.Driver;
i did this sample conn to exemplify

    #region BasicAuth
    public static class BasicAuth
    {
        public static IDriver DriverWithBasicAuth()
        {
            string uri = "bolt://192.168.0.224:7687";
            string user = "test0";
            string password = "test0";

            return GraphDatabase.Driver(uri, AuthTokens.Basic(user, password));
        }
    }
    #endregion

Session would go... var session = BasicAuth.DriverWithBasicAuth().Session();

string query = ("MATCH (source:dot {name: 'NODE'}),(target:Ponto {name: 'FINALNODE'})" +
                        " CALL gds.beta.shortestPath.dijkstra.stream('GrafoCuca3', {sourceNode: id(source),targetNode: id(target),relationshipWeightProperty: 'distance'})" +
                        " YIELD index, sourceNode, targetNode, totalCost, nodeIds, costs" +
                        " RETURN index, gds.util.asNode(sourceNode).nome AS sourceNodeName, gds.util.asNode(targetNode).nome AS targetNodeName, totalCost, [nodeId IN nodeIds | gds.util.asNode(nodeId).nome] AS nodeNames, costs" +
                        " ORDER BY index");
            var session = BasicAuth.DriverWithBasicAuth().Session();
            var result = session.Run(query);

I cant get to do a remote connection using Neo4jClient
the only connection i got to do was local it does not take another port nor bolt:\
using Neo4jClient;

IGraphClient Client = new Neo4jClient.GraphClient(new Uri("http://192.168.0.186:7474"),"test0","test0");
            Client.ConnectAsync().Wait();

plus i cant use Client.Connect()
just Client.ConnectAsync()

IsConnected = true

i would like to use Neo4J.client on 192.168.0.224:7687 like with the driver

but connection returns false
3X_a_f_af47af71bac4e7947087962a10f5e1318296c060.png

224 is a localserver
186 my host

1 ACCEPTED SOLUTION

charlotte_skard
Graph Buddy

OK, so when dealing with async in the .NET world, we're largely talking about using the await keyword to allow the code to execute wherever it wants (in essence). But. Not everyone has the ability to use async, so you need to be able to call it synchronously. You've done that already with the ConnectAsync() call. The Wait() basically is telling the code to wait for that bit to finish executing before carrying on.

So.

Let's tackle sync first.

The line you change is the var Result = query.ResultsAsync one - to become... var Result = query.ResultsAsync.Wait()

Job done! So let's have a quick perusal of the other bits...

Now, I'm a tiny bit wondering if the code worked, as to my eyes, the cypher is invalid, I think you need the () around the Match like so:

var query = client.Cypher
    .Match("(n)") //Added ( ) here
    .Return<string>("n");

OK, so now that should work. Next you will get JSON back, it'll be in the form defined here: Result formats - HTTP API - well similar and there are reasons we don't need to go into here...

The downside is that you have to parse that pesky JSON... I KNOW!

But - we can get around that, and that's kind of the point of the Neo4jClient - so we don't have to see that stuff!

From here on in, we're going to be looking at a bit of 'abstract thoughts' - as I don't know what your n looks like in the database. BUT let's assume it looks like this:

{
	name: 'Lucas',
	id: 1
}

We can create a class:

public class Data
{
	public string name {get;set;}
	public int id {get;set;}
}

and change our code to:

var query = client.Cypher
    .Match("(n)") //Added ( ) here
    .Return<Data>("n");

OR even BETTER!

var query = client.Cypher
    .Match("(n)") //Added ( ) here
    .Return(n => n.As<Data>());

2 things about the Data class - 1 don't call it that, call it something that makes sense - for instance Person would be way better here, or maybe Account... Data is terrible 😮

The second thing is that the current implementation of Data uses lowercase properties - which is C# naughtiness. So, 2 options here.

The first, and my preferred is to use UpperCamelCase for your properties when you store them, so your code has no translation steps. The second is to use [JsonProperty] so your class could look like:

public class Person // Name changed!!
{
	public string Name {get;set;}
	public int Id {get;set;}
}

or

public class Person // Name changed!!
{
	[JsonProperty("name")]
	public string Name {get;set;}

	[JsonProperty("id")]
	public int Id {get;set;}
}

Don't worry - we're nearly done. I said we'd start with sync, and so let's end with async

You can actually modify your code to be async, by making the Main method async... so. let's put it ALL together:

public static async Task Main(string[] args) // Change here!!
{
	var client = new BoltGraphClient("bolt://192.168.0.224:7687", "test0", "test0");
	await client.ConnectAsync(); // awaiting here

	var query = client
		.Cypher
		.Match("(n)")
		.Return(n => n.As<Person>()); //Using 'Person' class

	var result = await query.ResultsAsync; //Awaiting here

	Console.WriteLine(result);
	Console.ReadLine();
}

The last bit is upon us!

Dealing with the results

var is a blessing and a curse, in the good/bad old days you'd have had to be explicit, which would have made it a bit clearer as to what you get from this. So:

var result = await query.ResultsAsync;

is actually:

IEnumerable<Person> result = await query.ResultsAsync;

The T of the IEnumerable comes from the .Return bit - so - in your very first code for example, T was string.

Aaaanyhews - now we have an IEnumerable<Person> if you try to WriteLine it, you'll end up with something like:

System.Collections.IEnumerable{T}

being written out, which is not helpful. The easiest thing to do is a foreach and just write your results out like this:

foreach(var result in results)
{
	Console.WriteLine($"Name: {result.Name}, Id: {result.Id}");
}

So.

All the code.

public class Person
{
	public string Name {get;set;}
	public int Id {get;set;}
}

public static async Task Main(string[] args) // Change here!!
{
	var client = new BoltGraphClient("bolt://192.168.0.224:7687", "test0", "test0");
	await client.ConnectAsync(); 

	var query = client
		.Cypher
		.Match("(n)")
		.Return(n => n.As<Person>()); 

	var result = await query.ResultsAsync;

	foreach(var result in results)
	{
		Console.WriteLine($"Name: {result.Name}, Id: {result.Id}");
	}

	Console.ReadLine();
}

Phew!

View solution in original post

15 REPLIES 15

charlotte_skard
Graph Buddy

Hi Lucas,

The reason you can't connect to the bolt endpoint is because you are using the HTTP version of the client, you should instead be using the BoltGraphClient - I think - if you swap to that one, you'll be OK.

In terms of using Connect vs ConnectAsync version 4.x of the Client removed the non-async stuff, so it is only Async.

All the best

Chris

lucas_gadiel
Node Link

Hello Chris

i actually did try with it before... on the screenshot up top was the only wait i got it to work . With the bolt it gives me an exception. Problem with that exception is it does not tell me whats wrong so i can fix it.

Plus all the videos and most of the info i find on the web is quite old everyone still uses "connection" (No Async) so i thought i was doing something wrong lol

i found it weird because it does not say whats the error ... just multiple errors and thats that
3X_c_6_c6a0db8b974176140b5a69c644e365be05cda8f3.png

here is the info i get from it on the debugger. On the botton the IsConnected part is false.

by the way thanks for the help Chris ive been seeing a lot of ur posts here they are really helpfull

and if i change it to http (LocalHost) it Works
iit is also working just with the Neo4J.Driver thats what im finding weird same config on both... it should be connecting but the client only does the local http connection

Hey Lucas,

So, code wise you did:

var client = new BoltGraphClient("bolt://localhost:7687", "user", "pass");
client.ConnectAsync().Wait();

And that didn't work for you?
Normally - and this isn't always the case by any stretch of the imagination, but the AggregateException has a property called InnerException which I would expect to have the actual error.

Can you try with the code above? Also - try this:

var client = new BoltGraphClient("neo4j://localhost:7687", "user", "pass");
client.ConnectAsync().Wait();

All the best

Chris

lucas_gadiel
Node Link

BoltGraphClient needs a reference...
it does not recognize my reference i guess

here is what i am using
3X_e_7_e726b04da429c2336e55a1806588ade5ce97eb8a.png
i did add using Neo4J.Driver; (i actually tried all the other possibilities too)
i am re checked my Nuget packages and re installed them Neo4J.Driver and with the signed one as well is it possible that i am missing a require lib ? i did also check thee requirements before but looks like everything is ok

hmmmm interesting...

OK, so - let's see - the Driver should come down with Neo4jClient - so it might be worth using VS to remove both the Neo4j.Driver and Neo4jClient nuget packages, then just install the Neo4jClient - you should see that the Driver will be there as well.

Do you get that?

lucas_gadiel
Node Link

3X_b_f_bfba8a218251ebfbbb96f25b8e3858c76c15f9be.png
Yes they do come all together... all dependencies here
and by uninstalling and installing it worked 🙂
kinda weird because i did that before and it did not work guess seccond time's a charm
thank u very much !

lucas_gadiel
Node Link

actually still giving the error one or more errors ocurred

i can connect with the Neo4J Desktop

but not with the C# project and i have the same config on the desktop

this connection is being used on the desktop and it works perfectly

although now it does recognize the Neo4J.Driver for the BoltGraphClient

allow me to explain a bit better my setup i must be doing something wrong

i have a windows server running The Neo4J on the 192.168.0.224:7687

on the meanwhile i have computers that i want to access the data and while connecting through the Desktop it works (i checked ports/changed the settings file and everything ok installed everything for algo...)

mean while on the C# i am doing a project to run a few algorithims on Neo4J and display values on a UI. I have no idea what can be causing these connection issues do u think there is the possibility it is still firewall though it works throught the desktop Neo4J?

lucas_gadiel
Node Link

could it be the settings i need to change?

here is what i got:
IP
dbms.default_listen_address=0.0.0.0
BOLT
dbms.connector.bolt.enabled=true
dbms.connector.bolt.listen_address=:7687
dbms.connector.bolt.advertised_address=:7687

HTTP
dbms.connector.http.enabled=true

HTTPS
dbms.connector.https.enabled=false

And for the ALGORITHMS
dbms.security.procedures.unrestricted=apoc*,algo*,gds*
dbms.security.procedures.whitelist=apoc.,algo.,gds.*

Is it possible there is a config that does not allow me to connect with code but only with the desktop app?

charlotte_skard
Graph Buddy

Hmmm...

If desktop can connect - it should be fine. The main issues I've ever had with running remote is due to things like Firewalls - You have the default_listen_address setup correctly to allow remote calls. So it's not that.

I assume in a browser (Chrome etc) you can open up http://192.168.0.224:7474 ?

Are you able to share your project at all? In essence there's nothing I can see that would block anything here.

Hey Chris!
yeah i double checked the settings.

the only connection it allows to be made is
3X_8_e_8ee5c7d8e636585545c6b5e6a0cfa19229575155.png
when i do it with port 7474 it says:
this site can't be reached took too long to respond .

but i restarted everything commited everything and refreshed the solution and it worked

var client = new BoltGraphClient("bolt://192.168.0.224:7687", "test0", "test0");
                client.ConnectAsync().Wait();

worked just fine now i am testing the Cypher.
and returning the values i get
thanks for the help. and im also taking a look on ur movies example

ill start doing some matches and returns to test

Yay! The dream is alive!

Feel free to ask any questions!

lucas_gadiel
Node Link

Chris i am back.
should i create a new topic to ask about async query results? i did not find it on the community
if yes iill delete this and ask there...
the deal is i actually get to make my query but i am a bit confused on how should i recieve it or how do i even give the command for it to return... or even return as
this is my code:

            public static void BoltClient()
            {
                var client = new BoltGraphClient("bolt://192.168.0.224:7687", "test0", "test0");
                client.ConnectAsync().Wait();

                var query = client
               .Cypher
               .Match("n")
               .Return<string>("n");

                var Result = query.ResultsAsync;
                
                Console.WriteLine(Result);
                Console.ReadLine();
            }

not sure if i can simply... Console.WriteLine();
but even if i couldnt there should be values on the debugger

and i know that on dektop it returns as JSON :

it says: waiting for activation /method= null /result (not yet computered)
therefor i add the query to a queue but did not tell it to be executed?
i have been doing through the Neo4J Client Docs but did not find any info about it there.
im kinda new on with Neo4J.Client i found it awesome what u did on the .NET client binding for Neo4J
But im having a bit of trouble after this step ... or maybe even on this step as u can see on what i did on the code

charlotte_skard
Graph Buddy

OK, so when dealing with async in the .NET world, we're largely talking about using the await keyword to allow the code to execute wherever it wants (in essence). But. Not everyone has the ability to use async, so you need to be able to call it synchronously. You've done that already with the ConnectAsync() call. The Wait() basically is telling the code to wait for that bit to finish executing before carrying on.

So.

Let's tackle sync first.

The line you change is the var Result = query.ResultsAsync one - to become... var Result = query.ResultsAsync.Wait()

Job done! So let's have a quick perusal of the other bits...

Now, I'm a tiny bit wondering if the code worked, as to my eyes, the cypher is invalid, I think you need the () around the Match like so:

var query = client.Cypher
    .Match("(n)") //Added ( ) here
    .Return<string>("n");

OK, so now that should work. Next you will get JSON back, it'll be in the form defined here: Result formats - HTTP API - well similar and there are reasons we don't need to go into here...

The downside is that you have to parse that pesky JSON... I KNOW!

But - we can get around that, and that's kind of the point of the Neo4jClient - so we don't have to see that stuff!

From here on in, we're going to be looking at a bit of 'abstract thoughts' - as I don't know what your n looks like in the database. BUT let's assume it looks like this:

{
	name: 'Lucas',
	id: 1
}

We can create a class:

public class Data
{
	public string name {get;set;}
	public int id {get;set;}
}

and change our code to:

var query = client.Cypher
    .Match("(n)") //Added ( ) here
    .Return<Data>("n");

OR even BETTER!

var query = client.Cypher
    .Match("(n)") //Added ( ) here
    .Return(n => n.As<Data>());

2 things about the Data class - 1 don't call it that, call it something that makes sense - for instance Person would be way better here, or maybe Account... Data is terrible 😮

The second thing is that the current implementation of Data uses lowercase properties - which is C# naughtiness. So, 2 options here.

The first, and my preferred is to use UpperCamelCase for your properties when you store them, so your code has no translation steps. The second is to use [JsonProperty] so your class could look like:

public class Person // Name changed!!
{
	public string Name {get;set;}
	public int Id {get;set;}
}

or

public class Person // Name changed!!
{
	[JsonProperty("name")]
	public string Name {get;set;}

	[JsonProperty("id")]
	public int Id {get;set;}
}

Don't worry - we're nearly done. I said we'd start with sync, and so let's end with async

You can actually modify your code to be async, by making the Main method async... so. let's put it ALL together:

public static async Task Main(string[] args) // Change here!!
{
	var client = new BoltGraphClient("bolt://192.168.0.224:7687", "test0", "test0");
	await client.ConnectAsync(); // awaiting here

	var query = client
		.Cypher
		.Match("(n)")
		.Return(n => n.As<Person>()); //Using 'Person' class

	var result = await query.ResultsAsync; //Awaiting here

	Console.WriteLine(result);
	Console.ReadLine();
}

The last bit is upon us!

Dealing with the results

var is a blessing and a curse, in the good/bad old days you'd have had to be explicit, which would have made it a bit clearer as to what you get from this. So:

var result = await query.ResultsAsync;

is actually:

IEnumerable<Person> result = await query.ResultsAsync;

The T of the IEnumerable comes from the .Return bit - so - in your very first code for example, T was string.

Aaaanyhews - now we have an IEnumerable<Person> if you try to WriteLine it, you'll end up with something like:

System.Collections.IEnumerable{T}

being written out, which is not helpful. The easiest thing to do is a foreach and just write your results out like this:

foreach(var result in results)
{
	Console.WriteLine($"Name: {result.Name}, Id: {result.Id}");
}

So.

All the code.

public class Person
{
	public string Name {get;set;}
	public int Id {get;set;}
}

public static async Task Main(string[] args) // Change here!!
{
	var client = new BoltGraphClient("bolt://192.168.0.224:7687", "test0", "test0");
	await client.ConnectAsync(); 

	var query = client
		.Cypher
		.Match("(n)")
		.Return(n => n.As<Person>()); 

	var result = await query.ResultsAsync;

	foreach(var result in results)
	{
		Console.WriteLine($"Name: {result.Name}, Id: {result.Id}");
	}

	Console.ReadLine();
}

Phew!

cheers mate
saved my ass thank you very much cuz it worked like a charm
and i understood the process...

All hail Chris the god of Neo4J .Net lol

Ain't that the truth!