OK, so this is how the IStatementResult
is intended to work.
What's important to note is that whilst var result
is an IEnumerable
the underlying structure isn't an Array
or List<T>
but a stream of data.
When you call First()
you iterate the IEnumerable
and pull the first item from the stream, the next time you call First()
you get the first item from the stream - but in this case, because the stream has already yielded it's first item, you're getting the second.
Woah! Hard to read much?!?!
Imagine you have an array [1,2,3,4,5]
on a server somewhere, and this is streamed to you.
You call arr.First()
- this goes to the server and pulls down 1
. At this point, the server now has:
[2,3,4,5]
You then call arr.First()
- and the server now sends you 2
as - from it's point of view that is the first item.
I'm not sure if that's clearer or not - let me know if not.
Anyhews - if you want First()
to always work - you would need to do ToList()
, so for example:
void Main()
{
var driver = GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "neo"));
using (var session = driver.Session(AccessMode.Write))
{
Console.WriteLine("Just IEnumerable");
var result = session.ReadTransaction(s => s.Run("MATCH (m:Movie) RETURN m.title AS title, m.tagline AS tagline"));
WriteToScreen(result);
Console.WriteLine();
Console.WriteLine("Using ToList()");
var result2 = session.ReadTransaction(s => s.Run("MATCH (m:Movie) RETURN m.title AS title, m.tagline AS tagline"));
WriteToScreen(result2.ToList());
}
}
public static void WriteToScreen(IEnumerable<IRecord> result)
{
var value1 = result.First()["title"].As<string>();
var value2 = result.First()["tagline"].As<string>();
value1.Dump();
value2.Dump();
}
outputs:
Just IEnumerable
The Matrix
Free your mind
Using ToList()
The Matrix
Welcome to the Real World
The ToList
version doing what you're hoping for.
Now. The way you probably want to approach this - to avoid pulling everything from the DB in one go, is to do:
using (var session = driver.Session(AccessMode.Write))
{
var result = [...].WriteTransaction(tx => tx.Run[...]
var first = result.First();
var value1 = first["value1"].As<string>();
var value2 = first["value2"].As<string>();
[...]
}
Lastly - as to why changing VS made a difference, I can't explain - this should always work like this - are you 100% sure the code wasn't different?
All the best
Chris