README.md (11771B)
1 # QueryExpressionBuilder 2 Library for generating predicate functions for filtering database queries. 3 4 ## Description 5 This library helps create a predicate function for filtering database queries based on a model. 6 7 ## Instruction 8 To use the library, you need to create a model with properties for filtering. Properties in the model need to be marked with attributes.<br> 9 10 Currently, there are 3 attributes:<br> 11 12 Namespace QueryExpressionBuilder.Attributes.String - attributes for properties of type String<br> 13 StartWithAttribute - Indicates that a filter equivalent to the System.String.StartWith() function will be used for the property.<br> 14 ContainsAttribute - Indicates that a filter equivalent to the System.String.Contains() function will be used for the property.<br> 15 16 Namespace QueryExpressionBuilder.Attributes.Numbers - attribute for all properties that are numeric, including DateTime<br> 17 GreaterOrEqualAttribute - Indicates that a filter equivalent to the >= conditional expression will be used for the property.<br> 18 LessOrEqualAttribute - Indicates that a filter equivalent to the <= conditional expression will be used for the property.<br> 19 EqualsAttribute - Just compares values like in a function Equals.<br> 20 21 You need to pass the property name from the class representing the entity in the database to the attribute constructor. 22 23 ## Examples 24 Suppose we have an entity User, which is an entity in the database. 25 ```csharp 26 public class User : IEntity 27 { 28 public Guid Id { get; set; } 29 public string Name { get; set; } 30 public string Surname { get; set; } 31 public string Email { get; set; } 32 public DateTime BirthDate { get; set; } 33 public DateTime RegistrationDate { get; set; } 34 public string PasswodHash { get; set; } 35 public float Amount { get; set; } 36 } 37 ``` 38 To create a Query filter, we need to create a query model. 39 ```csharp 40 public class UserQuery 41 { 42 [QueryExpressionBuilder.Attributes.String.StartWith("Name")] 43 public string? Name { get; set; } 44 45 [QueryExpressionBuilder.Attributes.String.StartWith("Surname")] 46 public string? Surname { get; set; } 47 48 [QueryExpressionBuilder.Attributes.String.StartWith("Email")] 49 public string? Email { get; set; } 50 51 [QueryExpressionBuilder.Attributes.Numbers.GreaterOrEqual("BirthDate")] 52 public DateTime? FromBirthDate { get; set; } 53 54 [QueryExpressionBuilder.Attributes.Numbers.LessOrEqual("BirthDate")] 55 public DateTime? ToBirthDate { get; set; } 56 57 [QueryExpressionBuilder.Attributes.Numbers.GreaterOrEqual("RegistrationDate")] 58 public DateTime? FromRegistrationDate { get; set; } 59 60 [QueryExpressionBuilder.Attributes.Numbers.LessOrEqual("RegistrationDate")] 61 public DateTime? ToRegistrationDate { get; set; } 62 63 [QueryExpressionBuilder.Attributes.Numbers.GreaterOrEqual("Amount")] 64 public float? FromAmount { get; set; } 65 66 [QueryExpressionBuilder.Attributes.Numbers.LessOrEqual("Amount")] 67 public float? ToAmount { get; set; } 68 } 69 ``` 70 And now, in the controller method, which represents the endpoint, simply pass the UserQuery object to the ExpressionBuilder class, which will return the predicate function. 71 ```csharp 72 [ApiController] 73 [Route("[controller]")] 74 public class WeatherForecastController : ControllerBase 75 { 76 private readonly ILogger<WeatherForecastController> _logger; 77 private readonly IUserService userService; 78 79 public WeatherForecastController(ILogger<WeatherForecastController> logger, IUserService _userService) 80 { 81 userService = _userService; 82 _logger = logger; 83 } 84 85 /// <summary> 86 /// Method for get users 87 /// </summary> 88 /// <param name="queryParams">Object containing filtering parameters</param> 89 /// <returns>Returns a list of users</returns> 90 [HttpGet("[controller]/GetUsers")] 91 public async Task<IEnumerable<User>> GetUsers([FromQuery] UserQuery queryParams) 92 { 93 //Generating a predicate based on parameters 94 var predicate = ExpressionBuilder.GetPredicate<User, UserQuery>(queryParams); 95 //We pass the predicate to the service and return the result 96 var result = await userService.GetUsers(predicate); 97 return result; 98 } 99 } 100 ``` 101 Now, when sending a request to the database<br> 102 https://localhost:7001/GetUsers?Name=M&FromBirthDate=2000-01-01&ToBirthDate=2040-01-01&FromAmount=1000<br> 103 We get an SQL query. 104 ```sql 105 SELECT "u"."Id", "u"."Amount", "u"."BirthDate", "u"."Email", "u"."Name", "u"."PasswodHash", "u"."RegistrationDate", "u"."Surname" 106 FROM "Users" AS "u" 107 WHERE instr("u"."Name", 'M') > 0 AND "u"."BirthDate" >= '2000-01-01 00:00:00' AND "u"."BirthDate" <= '2040-01-01 00:00:00' AND "u"."Amount" >= 1000 108 ``` 109 ## License 110 This project is distributed under the [MIT](https://opensource.org/licenses/MIT) license, which allows free use, modification, and distribution of the code in accordance with the terms of the MIT license. 111 <br><br><br> 112 113 # QueryExpressionBuilder 114 Библиотека для генирации функций-предикатов для фильтрирования запросов в БД. 115 116 ## Описание 117 Данная библиотека помогает создать функцию-предикат для фильтрирования запросов в БД на основе модели. 118 119 ## Инструкция 120 Для работы библиотеки необходимо создать модель с свойствами для фильтрации.<br> 121 Свойства в модели необходимо пометить атрибутами.<br> 122 123 На данный момент существует 3 атрибута:<br> 124 125 Пространство имен QueryExpressionBuilder.Attributes.String - атрибуты для свойств типа String<br> 126 StartWithAttribute - Означает, что дял свойства будет использоватся фильтр с аналогом функции System.String.StartWith()<br> 127 ContainsAttribute - Означает, что дял свойства будет использоватся фильтр с аналогом функции System.String.Contains()<br> 128 129 Пространство имен QueryExpressionBuilder.Attributes.Numbers - атрибут для всех свойств которые ввляются числовыми, в том числе DateTime<br> 130 GreaterOrEqualAttribute - Означает, что для свойства будет использоваться фильтр с аналогом условного выражения >=<br> 131 LessOrEqualAttribute - Означает, что для свойства будет использоваться фильтр с аналогом условного выражения <=<br> 132 EqualsAttribute - Просто то же самое, что и Equals.<br> 133 134 В конструктор атрибута необходимо передать название свойства из класса представляющий сущьность в БД.<br> 135 136 ## Примеры 137 Предположим у нас есть сущьность User, которая являеться сущьностью в БД. 138 ```csharp 139 public class User : IEntity 140 { 141 public Guid Id { get; set; } 142 public string Name { get; set; } 143 public string Surname { get; set; } 144 public string Email { get; set; } 145 public DateTime BirthDate { get; set; } 146 public DateTime RegistrationDate { get; set; } 147 public string PasswodHash { get; set; } 148 public float Amount { get; set; } 149 } 150 ``` 151 Для создания Query фильтра нам необходимо создать query-модель 152 ```csharp 153 public class UserQuery 154 { 155 [QueryExpressionBuilder.Attributes.String.StartWith("Name")] 156 public string? Name { get; set; } 157 158 [QueryExpressionBuilder.Attributes.String.StartWith("Surname")] 159 public string? Surname { get; set; } 160 161 [QueryExpressionBuilder.Attributes.String.StartWith("Email")] 162 public string? Email { get; set; } 163 164 [QueryExpressionBuilder.Attributes.Numbers.GreaterOrEqual("BirthDate")] 165 public DateTime? FromBirthDate { get; set; } 166 167 [QueryExpressionBuilder.Attributes.Numbers.LessOrEqual("BirthDate")] 168 public DateTime? ToBirthDate { get; set; } 169 170 [QueryExpressionBuilder.Attributes.Numbers.GreaterOrEqual("RegistrationDate")] 171 public DateTime? FromRegistrationDate { get; set; } 172 173 [QueryExpressionBuilder.Attributes.Numbers.LessOrEqual("RegistrationDate")] 174 public DateTime? ToRegistrationDate { get; set; } 175 176 [QueryExpressionBuilder.Attributes.Numbers.GreaterOrEqual("Amount")] 177 public float? FromAmount { get; set; } 178 179 [QueryExpressionBuilder.Attributes.Numbers.LessOrEqual("Amount")] 180 public float? ToAmount { get; set; } 181 } 182 ``` 183 И теперь в методе контроллера, который представляет конечную точку, нужно просто передать обьект UserQuery в класс ExpressionBuilder, который вернет функцию-предикат. 184 ```csharp 185 [ApiController] 186 [Route("[controller]")] 187 public class WeatherForecastController : ControllerBase 188 { 189 private readonly ILogger<WeatherForecastController> _logger; 190 private readonly IUserService userService; 191 192 public WeatherForecastController(ILogger<WeatherForecastController> logger, IUserService _userService) 193 { 194 userService = _userService; 195 _logger = logger; 196 } 197 198 /// <summary> 199 /// Метод получения юзеров 200 /// </summary> 201 /// <param name="queryParams">Объект содержащий параметры фильтрации</param> 202 /// <returns>Возвращает список юзеров</returns> 203 [HttpGet("[controller]/GetUsers")] 204 public async Task<IEnumerable<User>> GetUsers([FromQuery] UserQuery queryParams) 205 { 206 //Генерируем предикат на основе параметров 207 var predicate = ExpressionBuilder.GetPredicate<User, UserQuery>(queryParams); 208 //Передаем предикат в сервис и возвращаем результат 209 var result = await userService.GetUsers(predicate); 210 return result; 211 } 212 } 213 ``` 214 Теперь отправляя запрос<br> 215 https://localhost:7001/GetUsers?Name=M&FromBirthDate=2000-01-01&ToBirthDate=2040-01-01&FromAmount=1000<br> 216 в БД мы получаем SQL запрос 217 ```sql 218 SELECT "u"."Id", "u"."Amount", "u"."BirthDate", "u"."Email", "u"."Name", "u"."PasswodHash", "u"."RegistrationDate", "u"."Surname" 219 FROM "Users" AS "u" 220 WHERE instr("u"."Name", 'M') > 0 AND "u"."BirthDate" >= '2000-01-01 00:00:00' AND "u"."BirthDate" <= '2040-01-01 00:00:00' AND "u"."Amount" >= 1000 221 ``` 222 ## Лицензия 223 Этот проект распространяется под лицензией [MIT](https://opensource.org/licenses/MIT), которая разрешает свободное использование, изменение и распространение кода в соответствии с условиями лицензии MIT.