đ€ Questions techniques pour entretiens/missions
Q1 : Quelle est la diffĂ©rence entre Dapper et Entity Framework Core ?â
Réponse attendue :
-
Dapper : Micro-ORM, vous écrivez le SQL, mapping automatique uniquement
- Avantages : Performance maximale, contrĂŽle total du SQL
- Inconvénients : Plus de code à écrire, pas de migrations automatiques
-
EF Core : ORM complet, génÚre le SQL pour vous
- Avantages : Développement rapide, migrations automatiques, change tracking
- Inconvénients : SQL généré parfois non optimal, courbe d'apprentissage
Réponse courte : "Dapper pour la performance et le contrÎle, EF Core pour la productivité"
Q2 : Pourquoi utiliser Dapper plutĂŽt qu'ADO.NET pur ?â
Réponse attendue :
ADO.NET pur :
// Beaucoup de code boilerplate
var command = new SqlCommand(sql, connection);
var reader = command.ExecuteReader();
var products = new List<Product>();
while (reader.Read())
{
products.Add(new Product
{
Id = reader.GetInt32(0),
Name = reader.GetString(1),
Price = reader.GetDecimal(2)
});
}
Dapper :
// Mapping automatique, moins de code
var products = await connection.QueryAsync<Product>(sql);
Réponse courte : "Dapper = performance d'ADO.NET + productivité du mapping automatique"
Q3 : Comment Ă©vitez-vous les injections SQL avec Dapper ?â
Réponse attendue :
// â Mauvais - injection SQL
var sql = $"SELECT * FROM Users WHERE Username = '{username}'";
// â
Bon - paramÚtres sécurisés
var sql = "SELECT * FROM Users WHERE Username = @Username";
var user = await connection.QueryFirstOrDefaultAsync<User>(sql, new { Username = username });
Réponse courte : "Toujours utiliser des paramÚtres avec @, jamais de concaténation de strings"
Q4 : Comment gĂ©rer les transactions avec Dapper ?â
Réponse attendue :
using var connection = new SqlConnection(_connectionString);
await connection.OpenAsync();
using var transaction = await connection.BeginTransactionAsync();
try
{
await connection.ExecuteAsync(sql1, param1, transaction);
await connection.ExecuteAsync(sql2, param2, transaction);
await transaction.CommitAsync();
}
catch
{
await transaction.RollbackAsync();
throw;
}
RĂ©ponse courte : "BeginTransaction, passer la transaction Ă chaque requĂȘte, Commit/Rollback"
Q5 : Qu'est-ce que le problĂšme N+1 et comment l'Ă©viter ?â
Réponse attendue :
ProblĂšme :
// 1 requĂȘte pour les produits + N requĂȘtes pour les catĂ©gories
var products = await GetAllProductsAsync(); // 1 requĂȘte
foreach (var product in products)
{
product.Category = await GetCategoryAsync(product.CategoryId); // N requĂȘtes
}
Solution :
// 1 seule requĂȘte avec JOIN
var sql = @"
SELECT p.*, c.Id, c.Name
FROM Products p
INNER JOIN Categories c ON p.CategoryId = c.Id";
var products = await connection.QueryAsync<Product, Category, Product>(
sql, (product, category) => { product.Category = category; return product; });
RĂ©ponse courte : "Ăviter les requĂȘtes en boucle, utiliser des JOIN pour tout rĂ©cupĂ©rer en une fois"
Q6 : Comment faire du multi-mapping avec Dapper ?â
Réponse attendue :
var sql = @"
SELECT p.Id, p.Name, p.Price, c.Id, c.Name
FROM Products p
INNER JOIN Categories c ON p.CategoryId = c.Id";
var products = await connection.QueryAsync<Product, Category, Product>(
sql,
(product, category) =>
{
product.Category = category;
return product;
},
splitOn: "Id"); // Dapper split ici pour séparer Product et Category
Point clĂ© : Le splitOn indique oĂč Dapper doit "couper" pour crĂ©er le second objet.
Q7 : Le projet utilise dĂ©jĂ EF Core, pourquoi ajouter Dapper ?â
Réponse pragmatique :
"On peut combiner les deux ! EF Core pour le CRUD standard, Dapper pour les requĂȘtes complexes ou critiques en performance."
Exemple :
public class ProductService
{
private readonly AppDbContext _context; // EF Core
private readonly IDbConnection _connection; // Dapper
// CRUD simple avec EF Core
public async Task<Product> GetByIdAsync(int id)
=> await _context.Products.FindAsync(id);
// Rapport complexe avec Dapper
public async Task<List<SalesReport>> GetMonthlySalesAsync()
=> (await _connection.QueryAsync<SalesReport>(
"sp_GetMonthlySales",
commandType: CommandType.StoredProcedure)).ToList();
}
Q8 : Comment testez-vous du code utilisant Dapper ?â
Réponse attendue :
Approche 1 : Base de test réelle (recommandé)
[TestInitialize]
public async Task Setup()
{
// Utiliser une vraie DB de test (SQLite en mémoire par exemple)
_connection = new SqliteConnection("Data Source=:memory:");
await _connection.OpenAsync();
await _connection.ExecuteAsync("CREATE TABLE Products (...)");
}
Approche 2 : Abstraction avec interface
public interface IProductRepository
{
Task<List<Product>> GetAllAsync();
}
// Tests avec mock du repository
var mockRepo = new Mock<IProductRepository>();
Réponse courte : "Préférer une vraie DB de test, ou abstraire avec des interfaces pour mocker"
Q9 : La requĂȘte Dapper est lente, comment diagnostiquer ?â
Réponse pratique :
- Activer le profiling SQL
// Utiliser un outil comme MiniProfiler
var stopwatch = Stopwatch.StartNew();
var products = await connection.QueryAsync<Product>(sql);
stopwatch.Stop();
_logger.LogInformation("Query took {Ms}ms", stopwatch.ElapsedMilliseconds);
-
Vérifier le SQL généré
- Copier le SQL avec les paramĂštres dans SSMS/Azure Data Studio
- Vérifier le plan d'exécution
- Ajouter des index si nécessaire
-
ProblÚmes fréquents :
- Pas d'index sur les colonnes du WHERE/JOIN
- SELECT * au lieu de colonnes spécifiques
- ProblĂšme N+1
Q10 : Comment gĂ©rer les connexions avec Dapper ?â
Réponse attendue :
â Bon : using + pool automatique
public async Task<List<Product>> GetAllAsync()
{
using var connection = new SqlConnection(_connectionString);
// Pas besoin d'OpenAsync, Dapper le fait automatiquement
return (await connection.QueryAsync<Product>(sql)).ToList();
}
// Connection retournée au pool automatiquement
â Mauvais : rĂ©utiliser la mĂȘme connection
private SqlConnection _connection; // NON ! ProblĂšme de threading
public async Task<List<Product>> GetAllAsync()
{
return (await _connection.QueryAsync<Product>(sql)).ToList();
}
Réponse courte : "Toujours utiliser using pour les connexions, le pool ADO.NET gÚre la réutilisation"
đ Checklist de prĂ©parationâ
Avant un entretien/mission sur Dapper, assurez-vous de pouvoir :
- Expliquer la différence Dapper vs EF Core
- Ăcrire une requĂȘte avec paramĂštres sĂ©curisĂ©s
- Faire un multi-mapping avec JOIN
- Expliquer le problĂšme N+1
- Gérer une transaction
- Appeler une stored procedure
- Expliquer comment tester du code Dapper
- Diagnostiquer une requĂȘte lente