Au lieu d'utiliser une bibliothèque tierce pour les opérations de requête, je suggérerais plutôt d'écrire des requêtes par vous-même. Parce que l'utilisation de tout autre package tiers enlèverait le principal avantage de l'utilisation de dapper, c'est-à-dire la flexibilité d'écrire des requêtes.
Maintenant, il y a un problème avec l'écriture de la requête d'insertion ou de mise à jour pour l'objet entier. Pour cela, on peut simplement créer des helpers comme ci-dessous:
InsertQueryBuilder:
public static string InsertQueryBuilder(IEnumerable < string > fields) {
StringBuilder columns = new StringBuilder();
StringBuilder values = new StringBuilder();
foreach(string columnName in fields) {
columns.Append($ "{columnName}, ");
values.Append($ "@{columnName}, ");
}
string insertQuery = $ "({ columns.ToString().TrimEnd(',', ' ')}) VALUES ({ values.ToString().TrimEnd(',', ' ')}) ";
return insertQuery;
}
Désormais, en passant simplement le nom des colonnes à insérer, toute la requête sera créée automatiquement, comme ci-dessous:
List < string > columns = new List < string > {
"UserName",
"City"
}
string insertQueryValues = QueryBuilderUtil.InsertQueryBuilder(columns);
string insertQuery = $ "INSERT INTO UserDetails {insertQueryValues} RETURNING UserId";
Guid insertedId = await _connection.ExecuteScalarAsync < Guid > (insertQuery, userObj);
Vous pouvez également modifier la fonction pour renvoyer l'instruction INSERT entière en transmettant le paramètre TableName.
Assurez-vous que les noms de propriété de classe correspondent aux noms de champ dans la base de données. Ensuite, vous seul pouvez passer l'obj entier (comme userObj dans notre cas) et les valeurs seront automatiquement mappées.
De la même manière, vous pouvez également avoir la fonction d'assistance pour la requête UPDATE:
public static string UpdateQueryBuilder(List < string > fields) {
StringBuilder updateQueryBuilder = new StringBuilder();
foreach(string columnName in fields) {
updateQueryBuilder.AppendFormat("{0}=@{0}, ", columnName);
}
return updateQueryBuilder.ToString().TrimEnd(',', ' ');
}
Et utilisez-le comme:
List < string > columns = new List < string > {
"UserName",
"City"
}
string updateQueryValues = QueryBuilderUtil.UpdateQueryBuilder(columns);
string updateQuery = $"UPDATE UserDetails SET {updateQueryValues} WHERE UserId=@UserId";
await _connection.ExecuteAsync(updateQuery, userObj);
Bien que dans ces fonctions d'assistance également, vous devez transmettre le nom des champs que vous souhaitez insérer ou mettre à jour, mais au moins vous avez un contrôle total sur la requête et pouvez également inclure différentes clauses WHERE si nécessaire.
Grâce à ces fonctions d'assistance, vous enregistrerez les lignes de code suivantes:
Pour une requête d'insertion:
$ "INSERT INTO UserDetails (UserName,City) VALUES (@UserName,@City) RETURNING UserId";
Pour la requête de mise à jour:
$"UPDATE UserDetails SET UserName=@UserName, City=@City WHERE UserId=@UserId";
Il semble y avoir une différence de quelques lignes de code, mais quand il s'agit d'effectuer une opération d'insertion ou de mise à jour avec une table comportant plus de 10 champs, on peut sentir la différence.
Vous pouvez utiliser l'opérateur nameof pour passer le nom du champ dans la fonction afin d'éviter les fautes de frappe
Au lieu de:
List < string > columns = new List < string > {
"UserName",
"City"
}
Tu peux écrire:
List < string > columns = new List < string > {
nameof(UserEntity.UserName),
nameof(UserEntity.City),
}