me and my colleague we face with an issue. We have couple of SQL queries as strings.Here's an example:
public class Query
{
public static string CreditTransferId(string expectedValue, string table, int statusId, int messageTypeId, int destination103, int destination202, string StoreStatus202Id)
{
return $"SELECT top 1 Id from {table} where MessageId = '{expectedValue}' and FlowId=3 and StatusId={statusId} and MessageTypeId={messageTypeId} and " +
$" Destination103={destination103} and Destination202={destination202} and StoreStatus103Id is null and StoreStatus202Id {StoreStatus202Id}";
}
}
For now we have them returned as strings from methods inside the Query class. We want to refactor the code make it clean, since we have a method with more than 3 parameters which is pretty hard to use anyways.
How would you go about this? What's the cleanest way to organize SQL queries which needs a lot of parameters like we have in the code above? I'll really appreciate any answers that might improve the current state of our code.
Thanks!
Dynamic SQL is a very bad thing for a start as these are open to SQL injection, you should use parameterise queries and return a string.
"eg: SELECT top 1 Id from [Table] where [MessageId] = @messageId"
etc
So you dont need to pass in any values, you would add these to your list of SqlParamater's
The table name is probably pointless as this is related to the sql, so probably just add that into the sql string
This doesn't really need an extra class, just create the sql variable where you call it, so it right there if you need it?
..or use Stored Procedures
..or use Entity Framework
EF is great and you have to decide if that's what you want. There are some cases where it is not suitable. Of u decide to stick with plain text queries how about dividing queries into parts: FromBuilder JoinBuilder GroupBuilder Condition builder etc
ex.:
return @"
"+new TableIdSelectorBuilder(table).Get() +@"
"+new FromBuilder().Get(table) +@"
"+new TableConditionByIdBuilder(table).Get(I'd)+@"
";
EDIT: Stored procedures allow to change queries without publishing new app version but is a bit pain in the ass to work on a living organism. At least sometimes.
Hopefully this helps you a bit. I was figuring this out a long time ago too.
One advice that I have is: Try to use nameOf()
for column names (in case your domain model matches exactly your database structure).
Refactoring becomes a lot easier as well.
I created a class which allows me to create simple to medium complex queries (Select, Insert, Update, Joins, Deletes, Limit, Offset, ...). For most of the queries that I write I can use this query builder to get what I need and the code will look something like this:
var query = new QueryBuilder()
.Update(nameof(MyTable))
.Set(nameof(MyTable.Name), entity.Name)
.Set(nameof(MyTable.Firstname), entity.Firstname)
.WhereEquals(nameof(MyTable.Id), entity.Id)
.Build();
Unfortunately, I haven't found a good QueryBuilder out there yet. Therefore I created my own.
Another solution that I recently encountered is by doing the following:
var query = $$"""
SELECT * FROM {{nameof(MyTable)}
WHERE
XX
""";
This at least allows you to indent correctly and the code will remain clean.
I was also thinking about having bigger queries in separate files and include them in the Assembly. When you want to execute the query, you load the query from the file and run it like this.
You might also want to cache that query then, to not always load it from the file.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.