3

I'm developing an Web API in ASP.NET Core and we found ourselves in the need of running a background task for a large bulk insert operation. The model I'm inserting however contains a property of the Geometry type from the .NET Topology Suite.

public class GeometricData
{
    //...

    public Geometry Geometry { get; set; }
}

In order to bulk insert, I'm following a method I found here and it is quite performatic, but its implementation is beyond the scope of this question. Even though it is fast, an user could be inserting over one million records in one go for instance, so we decided to move this processing to a background task. The Hangfire extension looked like something that could save us a lot of time at first, but it doesn't seem to handle well the Geometry type. In the code below, the BackgroundTask method might as well be an empty method:

public Task BulkInsert(IEnumerable<GeometricData> list)
{
    BackgroundJob.Enqueue(() => BackgroundTask(list));

    return Task.CompletedTask;
}   

Just the act of passing a list of Geometry as a parameter to BackgroundTask in the action for Enqueue will throw the unfortunate error:

Self referencing loop detected for property 'CoordinateValue' with type 'NetTopologySuite.Geometries.Coordinate'. Path '[0].Geometry.Coordinates[0]'.

As a matter of fact, Coordinates (a NTS class) does reference itself:

enter image description here

No idea why they would do that, but they did. Regardless, everything worked just fine up until now, but unless I manage to find a solution to this (or even maybe work my way around it), I'm gonna be in a heap of trouble implementing a background worker from scratch (I'll be using the Worker Service, in case anyone is wondering). Any pointers?

makoshichi
  • 2,310
  • 6
  • 25
  • 52
  • `Coordinates` is no class of NTS. It is a property of `Geometry` which is of type Coordinate[]. The question is why your method accesses it in the first place. – FObermaier Mar 18 '20 at 11:03
  • A blind shot : you can try a custom serializer, like this `Hangfire.Common.JobHelper.SetSerializerSettings(new JsonSerializerSettings{Converters = new List() { new MyCoordinateJsonConverter()}});` where `MyCoordinateJsonConverter` is `JsonConverter` which takes care of self referencing – jbl Mar 19 '20 at 07:15
  • 1
    Dont run background.enqueue within a task... hangfire jobs are tasks already – Jawad Mar 22 '20 at 06:03

2 Answers2

0

Man, Add JsonIgnoreAttribute above Geometry and Coordinates, additionally: check the following link: newtonsoft.com/json/help/html/PropertyJsonIgnore.htm

0

Hangfire will attempt to serialise any parameters passed into the function so it can replay it during any recurring jobs. I assume you are using the method something like so:

RecurringJob.AddOrUpdate("test", () => BulkInsert(theList), Cron.Minutely);

Instead if possible try to access the list within the function instead so Hangfire will not serialise it.

RecurringJob.AddOrUpdate("test", () => BulkInsert(), Cron.Minutely);


public Task BulkInsert()
{
    var list = <theListFromSomewhere>;
    BackgroundJob.Enqueue(() => BackgroundTask(list));

    return Task.CompletedTask;
}  
Nick Spicer
  • 2,279
  • 3
  • 21
  • 26