Head's Up! These forums are read-only. All users and content have migrated. Please join us at community.neo4j.com.
03-05-2021 11:59 AM
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
224 is a localserver
186 my host
Solved! Go to Solution.
03-10-2021 03:01 AM
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!
03-07-2021 06:52 AM
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
03-08-2021 05:16 AM
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
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
03-08-2021 06:23 AM
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
03-08-2021 07:40 AM
BoltGraphClient needs a reference...
it does not recognize my reference i guess
here is what i am using
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
03-08-2021 08:48 AM
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?
03-08-2021 10:50 AM
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 !
03-08-2021 11:31 AM
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?
03-08-2021 11:44 AM
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?
03-09-2021 01:32 AM
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.
03-09-2021 08:34 AM
Hey Chris!
yeah i double checked the settings.
the only connection it allows to be made is
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
03-09-2021 08:59 AM
Yay! The dream is alive!
Feel free to ask any questions!
03-09-2021 12:23 PM
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
03-10-2021 03:01 AM
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!
03-10-2021 05:29 AM
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
03-10-2021 05:49 AM
Ain't that the truth!
All the sessions of the conference are now available online