EF CORE 2.2 - Les nouveautés
La version 2.2 d'EF CORE a été publiée il y a quelques semaines, je vais donc en profiter pour faire un petit article pour résumer les 3 nouveautés mises en avant par Microsoft sur la documentation officielle. Si vous souhaitez plus d'informations sur un des points évoqués ci-dessous, je vous invite a lire le détail complet sur la documentation officielle.
Spatial Data
Le support des données de type spatial a été ajouté à EF Core. Ce type de donnée présent dans les BDD, permet de réaliser des opérations basées sur des positions physiques (distance, le plus proche, le plus près, ...), mais également des opérations basées sur le rectangle d'un objet. Afin de supporter cela, EF Core, se base sur la librairie NetTopologySuite.
Attention, il n'y a que quelques provider (liste ci-dessous) qui supportent les données de type spatial, et certaines opérations ne sont pas supportées par tous. Pour utiliser ce support, il faut ajouter le package NuGet adéquat en fonction du provider que vous utilisez :
- SQL Server : Microsoft.EntityFrameworkCore.SqlServer.NetTopologySuite
- SQLite : Microsoft.EntityFrameworkCore.Sqlite.NetTopologySuite
- InMemory : NetTopologySuite
- PostgreSQL : Npgsql.EntityFrameworkCore.PostgreSQL.NetTopologySuite
L'idée ici n'étant pas d'expliquer comment fonctionne les opérations liées aux données spatiales, mais bien de montrer le support directement en LINQ de ces opérations :
var geometryFactory = NtsGeometryServices.Instance.CreateGeometryFactory(srid: 4326); var currentLocation = geometryFactory.CreatePoint(48.852588, 2.371924); var nearestCity = db.Cities .OrderBy(c => c.Location.Distance(currentLocation)) .FirstOrDefault(); var currentCountry = db.Countries .FirstOrDefault(c => c.Border.Contains(currentLocation));
Owned Entity Types
Les types d'entités owned ont été ajoutés depuis la version 2.0 d'EF Core. Cela permet de mapper des types d'entités uniquement à travers des relations, soit en utilisant un attribut soit en fluent dans la méthode OnModelCreating :
[Owned] public class StreetAddress { public string Street { get; set; } public string City { get; set; } } public class Order { public int Id { get; set; } public StreetAddress ShippingAddress { get; set; } } // OnModelCreating modelBuilder.Entity<Order>().OwnsOne(p => p.ShippingAddress);
Dans la version 2.2, le mapping peut maintenant se faire sur des relations multiples !
modelBuilder.Entity<Distributor>().OwnsMany(p => p.ShippingCenters, a => { a.HasForeignKey("DistributorId"); a.Property<int>("Id"); a.HasKey("DistributorId", "Id"); });
Query Tags
Les Query Tags permettent d'ajouter des logs dans les requêtes SQL générées par Entity Framework à des fins de traçabilité, d'audit ...
Pour mettre en place les Query Tags, il faut utiliser la méthode TagWith disponible sur les IQueryable, cette méthode prend une chaîne de caractères en paramètre. Voici un exemple de leur utilisation :
var query = ctx.Employees .TagWith("Recherche par email") .Where(e => e.Email == search); if (level != null) { query = query .TagWith(@"Avec filtre sur le niveau") .Where(e => e.Level == level); } var employees = await query.ToListAsync();
Ce qui est généré côté SQL :
-- Recherche par email -- Avec filtre -- sur le niveau SELECT [e].[Email], [e].[Level] FROM [Employees] AS [e] WHERE [e].[Email] = @p0 AND [e].[Level] = @p1
Il est donc possible d'utiliser les Query Tags a plusieurs reprises dans la même requête, ainsi que de mettre une chaîne de caractères avec des sauts de ligne. Attention cependant, la chaîne de caractères n'est pas paramétrable, elle doit être fixe.
Pour ma part, ces nouveautés sont intéressantes, mais je n'ai pas encore eu de problématiques liées aux Spacial Data et types d'entités owned, ni l’occasion de les mettre en pratique aussi bien dans mes projets professionnels et personnels. Concernant, les Query Tags, c'est quelque chose qui n'est pas très coûteux à mettre en place, qui peut même être ajouté dans les règles de développement. Ceci, dans l'optique de tracer au maximum les requêtes effectuées à la base de données et pourquoi pas d'optimiser au maximum les différentes requêtes générées.
Commentaires