Neo4jMapper Released

Neo4jMapper is a .NET Framework library used to map Neo4j cypher values onto your entity models.

In the beginning…

At last, I’ve finally got around to realising two of my goals in software development: to write a blog and to publish an open source project. Well here we are today, this is my blog which I created so that I can talk about my new project, Neo4jMapper.

I work at Barnardos Australia in a small development team, and our core product is a Case Management System called MyStory, which runs on ASP.NET MVC with a Neo4j back-end. And until now, we’ve used the other cypher mapper called Neo4jClient. In fact, Neo4jClient project was started at Barnardos by our friends at Readify who also contributed to the early development of MyStory.

So fast-forward 7 or 8 years and we see a few things have changed. When Neo4jClient was first started, it was early days for Neo4j and cypher. Actually, from what I recall, Neo4j initially used the Gremlin query language, and initial development of Neo4jClient supported only this language. Later on, when Cypher Query Language emerged, Neo4jClient was adapted to support it. From there, things settled down and Neo4jClient has largely been stable, and we have written dozens of repositories using Neo4jClient, some of which have been running in production for many years.

But things aren’t perfect. For one, we are experiencing some performance issues. Well-optimised cypher queries which take only milliseconds to return results when executed in the query browser, take exponentially longer when executed from code. There’s a sneaky suspicion that this is due to the serialization methods which convert the JSON data returned from Neo4j’s REST endpoint into model instances. Also, we’re seeing an abnormal amount of aborted transactions, especially with async code.

And now things have changed somewhat due to Neo4j (from version 3) providing first-class driver support for all major programming languages including .NET through their Neo4j.Driver library, and the Bolt protocol.

Of course, Neo4jClient has been updated to support Bolt, but perf and transaction issues remain, and until recently, Neo4jClient has not supported the new temporal types introduced in recent Neo4j versions.

So about 6 months ago we looked into the possibility we could use Neo4j.Driver in place of Neo4jClient. But as you may be aware, Neo4j.Driver is kind of low-level. Whilst you can execute a query and return the results, it is quite a bit of effort to manually map those results onto model instances. So we thought we’d give it a go and write a new library…

Introducing Neo4jMapper

Neo4jMapper is a .NET Framework library used to map Neo4j cypher values onto your entity models. It uses ServiceStack.Text mapper to convert the records returned by Neo4j.Driver into instances of your entities, and it provides utilities to convert those entities back into a format Neo4j.Driver can use to update the database.

var cursor = await Session.RunAsync(@"
  MATCH (person:Person {name: 'Cuba Gooding Jr.'})-[:ACTED_IN]->(movie:Movie)
  RETURN person, COLLECT(movie) AS movies");

var actor = await cursor
  .MapSingleAsync((Person person, IEnumerable<Movie> movies) =>
  {
    person.MoviesActedIn = movies;
    return person;
  });

actor.name.Should().Be("Cuba Gooding Jr.");
actor.born.Should().Be(1968);
actor.MoviesActedIn.Count().Should().Be(4);

Neo4jMapper is like Dapper, in that it assists with (de)serialisation, but stays out of the way, allowing you to use Neo4j.Driver as it was intended.

See our GitHub repository for code and tests. Nugets can be downloaded here.

Update October, 2022
Repository renamed and moved to https://github.com/neildobson-au/Neo4j.Mapper