Вместо того, чтобы использовать какую-либо стороннюю библиотеку для операций с запросами, я бы предпочел писать запросы самостоятельно. Потому что использование любых других сторонних пакетов лишило бы главного преимущества использования dapper, то есть гибкости при написании запросов.
Теперь существует проблема с написанием запроса вставки или обновления для всего объекта. Для этого можно просто создать помощников, как показано ниже:
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;
}
Теперь, просто передавая имя столбца для вставки, весь запрос будет создан автоматически, как показано ниже:
List < string > columns = new List < string > {
"UserName",
"City"
}
//QueryBuilder is the class having the InsertQueryBuilder()
string insertQueryValues = QueryBuilderUtil.InsertQueryBuilder(columns);
string insertQuery = $ "INSERT INTO UserDetails {insertQueryValues} RETURNING UserId";
Guid insertedId = await _connection.ExecuteScalarAsync < Guid > (insertQuery, userObj);
Вы также можете изменить функцию, чтобы она возвращала весь оператор INSERT, передав параметр TableName.
Убедитесь, что имена свойств класса совпадают с именами полей в базе данных. Только тогда вы можете передать весь объект (как в нашем случае userObj), и значения будут отображены автоматически.
Таким же образом у вас может быть вспомогательная функция для запроса 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(',', ' ');
}
И используйте это как:
List < string > columns = new List < string > {
"UserName",
"City"
}
//QueryBuilder is the class having the UpdateQueryBuilder()
string updateQueryValues = QueryBuilderUtil.UpdateQueryBuilder(columns);
string updateQuery = $"UPDATE UserDetails SET {updateQueryValues} WHERE UserId=@UserId";
await _connection.ExecuteAsync(updateQuery, userObj);
Хотя и в этих вспомогательных функциях вам также нужно передать имя полей, которые вы хотите вставить или обновить, но, по крайней мере, у вас есть полный контроль над запросом, и вы также можете включать различные предложения WHERE по мере необходимости.
С помощью этих вспомогательных функций вы сохраните следующие строки кода:
Для вставки запроса:
$ "INSERT INTO UserDetails (UserName,City) VALUES (@UserName,@City) RETURNING UserId";
Для запроса на обновление:
$"UPDATE UserDetails SET UserName=@UserName, City=@City WHERE UserId=@UserId";
Кажется, есть разница в несколько строк кода, но когда дело доходит до выполнения операции вставки или обновления таблицы, содержащей более 10 полей, можно почувствовать разницу.
Вы можете использовать оператор nameof для передачи имени поля в функции, чтобы избежать опечаток
Вместо того:
List < string > columns = new List < string > {
"UserName",
"City"
}
Ты можешь написать:
List < string > columns = new List < string > {
nameof(UserEntity.UserName),
nameof(UserEntity.City),
}