Neo4jMapper Update

Neo4jMapper v1.0.8 now supports async enumerable streams.

Version 1.0.8

Released December 4, 2019, version 1.0.8 introduces the following new features:

  1. Support async enumerable streams via IAsyncEnumerable C# 8 / NET Standard 2.1 / NET Core 3.0
  2. Improve support of null values in Temporal clr types in auto mappers
  3. Support mapping of IRelationship objects
  4. Updated CI to support NET Core 3.0 projects
  5. Updated ServiceStack.Text & Neo4j.Driver packages

C# 8 Async Streams support

New version now supports async streams via IAsyncEnumerable and the new AsyncResults extension method.

var cursor = await Session.RunAsync(@"
  MATCH (movie:Movie)
  RETURN movie
  ORDER BY movie.released");

var movies = await cursor.AsyncResults()
  .Map<Movie>()
  .TakeWhile(m => m.released < 2000)
  .ToListAsync(); 
  
movies.Count.Should().Be(23);
movies.Last().released.Should().Be(1999);

The new AsyncResults method takes IStatementResultCursor result from a statement execution RunAsync and returns an IAsyncEnumerable<IRecord>. This can be passed to a new set of Map<T> overloads which perform mapping as before and returning a modified IAsyncEnumerable<T> which can be further enumerated.

In this example, we're using TakeWhile which will enumerate records until the predicate evaluates true. What this does is to cease fetching (or streaming) records from the database which can be a much more efficient way of performing client-side filters than to fetch all the results and then discard some.

Improved null handling in temporal clr mapping

Neo4jMapper makes use of ServiceStack.Text for all mapping duties. To easily map between Neo4j temporal types and .NET clr equivalent types, AutoMapping.RegisterConverter method is used to automate this.

AutoMapping.RegisterConverter<LocalDate, DateTime>(localDate => localDate?.ToDateTime() ?? default);
AutoMapping.RegisterConverter<LocalDate, DateTime?>(localDateTime => localDateTime?.ToDateTime());
AutoMapping.RegisterConverter<DateTime, LocalDate>(dateTime => new LocalDate(dateTime));
AutoMapping.RegisterConverter<DateTime?, LocalDate>(dateTime => dateTime.HasValue ? new LocalDate(dateTime.Value) : null);

When a source value of LocalDate is found and should be mapped to a target type of DateTime then the above registrations are set-up so the conversion happens automatically. The above registration (and others temporal types) also support nullable types on either source or target.

Support mapping of IRelationship objects

Neo4jMapper can now map metadata stored in a relationship.

var cursor = await Session.RunAsync(@"
    CREATE (:Person)-[knows:KNOWS]->()
    SET knows = {relationship: 'Brother',current:true}
    RETURN knows");

var knows = await cursor.MapSingleAsync<Knows>();

knows.relationship.Should().Be("Brother");
knows.current.Should().BeTrue();

Other changes

  • Test projects now target NET Core 3.0. Updated Travis & Appveyor projects accordingly.
  • Updated ServiceStack.Text & Neo4j.Driver packages

What's Next?

Work will continue on Neo4jMapper. Next up for consideration:

  • Neo4j.Driver v4.0 has been released which significantly changes its internal APIs. This may involve breaking changes to Neo4jMapper APIs.
  • Improve parameter support so that models containing complex types including enums get converted to strings automatically.
Update October, 2022
Repository renamed and moved to https://github.com/neildobson-au/Neo4j.Mapper