Entity Framework Core 2.2 Preview 2 – données spatiales

Ca y est, Entity Framework Core supporte les données spatiales avec la sortie de la version 2.2 Preview 2. Regardons comment nous en servir. 

Pre-requis

Code

Ajouter le package Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite qui est disponible en prerelease pour l’instant.

Dans la preview 2, les type spatiaux ne sont pas supportés par la commande Scaffold-DbContext.

PM> Scaffold-DbContext "Data Source=..." Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models -Force
Could not find type mapping for column 'dbo.Events.EventLocation' with data type 'geography'. Skipping column.

Il faut alors les ajouter manuellement dans les modèles.  A noter que l’approche code first quant à elle fonctionne.

using NetTopologySuite.Geometries;
//...
public partial class Events
{
   public int Id { get; set; }
   public string Title { get; set; }
   public Point EventLocation { get; set; }
}

Une fois le package installé, il faut activer la gestion des données spatiales dans le DBContext en appelant UseNetTopologySuite() dans UseSqlServer() dans OnConfiguring() ou dans AddDbContext().

services.AddDbContext(
   options =>
      options.UseSqlServer("Data Source=...",
   sqlOptions => sqlOptions.UseNetTopologySuite()));
   

Il est maintenant possible de manipuler ces types.

using (TestContext testContext = new TestContext())
{
    // Insert
    testContext.Events.AddRange(
        new Events
        {
            Id = 100,
            Title = "E14",
            EventLocation = new NetTopologySuite.Geometries.Point(1, 4) { SRID = 4326 }
        },
        new Events
        {
            Id = 101,
            Title = "E41",
            EventLocation = new NetTopologySuite.Geometries.Point(4, 1) { SRID = 4326 }
        }
    );

    testContext.SaveChanges();

    // display
    var v = testContext.Events;
    Console.WriteLine($"Title - EventLocation.AsText()");
    foreach (var e in v)
    {
        Console.WriteLine($"{e.Title} - {e.EventLocation.AsText()}");
    }
}

et voici le résultat dans la console

Title - EventLocation.AsText()
E14 - POINT (1 4)
E41 - POINT (4 1)

ASP.Net Core MVC

J’ai testé avec ASP.Net Core MVC et la génération de contrôleur et vues fonctionne.

Il est possible d’aller plus loin, comme en cherchant les points à proximité d’un autre point.

public async Task Near()
{
   Point point = new Point(3, 0) { SRID = 4326 };
   return View(await _context.Events
      //.Where(e => e.EventLocation.Distance(point) < x)
      .OrderBy(e => e.EventLocation.Distance(point))
      .Take(3)
      .ToListAsync());
}

et voici le résultat :

 

Cette preview va dans la bonne direction.

DotNet Core devrait toucher un public plus large avec cette fonctionnalité qui était attendue depuis longtemps par la communauté.

**Références : **

Announcing Entity Framework Core 2.2 Preview 2