Derniers tips / Mémos
Modélise nativement « exactement l'un de ces types », avec un switch exhaustif vérifié par le compilateur.
Fin des state machines générées par le compilateur : moins d'allocations et des stack traces enfin lisibles.
Recherche sémantique directement dans SQL Server 2025, sans base vectorielle séparée, en LINQ typé.
Framework UI cross-platform pour .NET : Windows, macOS, Linux, iOS, Android et WebAssembly.
Découvrez les nouvelles APIs asynchrones pour la compression ZIP et les améliorations de performance dans .NET 10
Facet : générateur de projections pour Entity Framework
Facet automatise la création de DTOs et de mappings pour vos entités Entity Framework, réduisant le code répétitif.
Installation
Installez le package NuGet Facet et référencez‑le dans votre projet pour activer le générateur de code.
dotnet add package Facet --version 2.5.1Utilisation de base
Ajoutez l'attribut [Facet] sur une classe partielle pour générer automatiquement les propriétés et la projection.
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public DateTime CreatedAt { get; set; }
public List<Order> Orders { get; set; }
}
// Définition de la projection avec l'attribut [Facet]
[Facet]
public partial class UserDto
{
// Propriétés définies manuellement
public int Id { get; set; }
public string Name { get; set; }
// Propriétés générées automatiquement par Facet
// basées sur la classe User
}Code généré
Facet génère automatiquement les propriétés manquantes et une expression de projection pour mapper efficacement vos entités.
// Code généré automatiquement par Facet
partial class UserDto
{
public string Email { get; set; }
public DateTime CreatedAt { get; set; }
// Expression de projection générée
public static Expression<Func<User, UserDto>> Projection =>
user => new UserDto
{
Id = user.Id,
Name = user.Name,
Email = user.Email,
CreatedAt = user.CreatedAt
};
// Méthode de projection
public static UserDto FromUser(User user) =>
new UserDto
{
Id = user.Id,
Name = user.Name,
Email = user.Email,
CreatedAt = user.CreatedAt
};
}Intégration avec Entity Framework
Utilisez les expressions de projection générées directement dans vos requêtes LINQ pour traduire en SQL optimal.
public class UserService
{
private readonly ApplicationDbContext _context;
public UserService(ApplicationDbContext context)
{
_context = context;
}
// Utilisation avec Entity Framework
public async Task<List<UserDto>> GetUsersAsync()
{
return await _context.Users
.Select(UserDto.Projection)
.ToListAsync();
}
// Plus efficace que :
// return await _context.Users
// .ToListAsync()
// .Select(user => new UserDto { ... });
}Projections complexes
Composez des DTOs avancés, ajoutez des propriétés calculées et naviguez entre projections pour des vues riches.
[Facet]
public partial class UserDetailDto
{
public int Id { get; set; }
public string Name { get; set; }
// Propriété calculée personnalisée
public string DisplayName => $"{Name} ({Email})";
// Navigation vers une autre projection
public List<OrderDto> RecentOrders { get; set; }
// Propriété conditionnelle
[ConditionalProperty]
public bool IsActive => CreatedAt > DateTime.UtcNow.AddMonths(-6);
}
[Facet]
public partial class OrderDto
{
public int Id { get; set; }
public decimal Amount { get; set; }
public DateTime OrderDate { get; set; }
}Configuration avancée
Contrôlez finement la génération via des attributs (Ignore, Property, IncludeNavigationProperties, etc.).
[Facet(
SourceType = typeof(User),
IncludeNavigationProperties = false,
GenerateMapper = true)]
public partial class UserSummaryDto
{
public int Id { get; set; }
public string Name { get; set; }
// Exclusion explicite d'une propriété
[FacetIgnore]
public string Email { get; set; }
// Mapping personnalisé
[FacetProperty(SourceProperty = "Email")]
public string ContactEmail { get; set; }
}Performance
Les projections générées s'exécutent côté base de données via LINQ to Entities, réduisant le volume de données transférées.
// ❌ Inefficace - charge toutes les données en mémoire
var users = await _context.Users
.Include(u => u.Orders)
.ToListAsync();
var userDtos = users.Select(u => new UserDto
{
Id = u.Id,
Name = u.Name
}).ToList();
// ✅ Efficace - projection au niveau SQL
var userDtos = await _context.Users
.Select(UserDto.Projection)
.ToListAsync();
// SQL généré :
// SELECT [u].[Id], [u].[Name]
// FROM [Users] AS [u]Bonnes pratiques
Nommez clairement vos DTOs (Suffixe Dto/ReadModel)
Exposez uniquement les propriétés utiles
Une projection par cas d'usage
Intégrez la génération au build CI
Documentez les champs calculés
Alternatives
AutoMapper, Mapster ou la projection manuelle via LINQ sont des options si vous ne souhaitez pas de génération de code.
// AutoMapper
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<User, UserDto>();
});
// Mapster
var userDto = user.Adapt<UserDto>();
// Projection manuelle avec Entity Framework
var userDtos = await _context.Users
.Select(u => new UserDto
{
Id = u.Id,
Name = u.Name,
Email = u.Email
})
.ToListAsync();Conclusion
Facet accélère la création de DTOs performants et maintenables. Il s'intègre naturellement avec EF Core via des projections typées.