An older desktop application can have rules distributed across a screen, a service, a stored procedure and a report. A short method is not evidence that the change is small.
Start with the behavior that a person can observe: the input, the saved result, and what another screen reads afterward.
Trace one complete workflow
For an invoice search, follow the search field into its query and then into the rows shown on screen. Check whether the report uses the same filter. Find the code that writes the relevant records before changing how they are read.
Write down one ordinary case, one empty result and the case that triggered the change. Existing production data can reveal assumptions that a freshly created database will not.
Avoid changing names, calculations and database access patterns in the same patch unless the fix requires them. Separate changes are easier to review and easier to reverse.
Keep input out of SQL text
This example uses System.Data.SqlClient on .NET Framework 4.8. The table is illustrative; use the actual schema and access rules in the application.
using System;
using System.Data;
using System.Data.SqlClient;
public static int GetInvoiceCount(string connectionString, int accountId)
{
if (accountId <= 0)
throw new ArgumentOutOfRangeException(nameof(accountId));
using (var connection = new SqlConnection(connectionString))
using (var command = connection.CreateCommand())
{
command.CommandText =
"SELECT COUNT(*) FROM dbo.Invoices WHERE AccountId = @accountId";
command.Parameters.Add("@accountId", SqlDbType.Int).Value = accountId;
connection.Open();
return (int)command.ExecuteScalar();
}
}
The parameter supplies a value separately from the command text. Its type matches the assumed SQL int column. String parameters also need a length that matches the schema. Parameterization does not provide authorization: the caller still has to be allowed to read that account.
This method is synchronous. Do not call a slow database operation directly from a UI event and assume the screen will stay responsive. See the separate async note when choosing the calling flow.
Verify the affected behavior
Run the workflow against controlled data and check both the screen and any affected report. For a write change, verify the persisted values and how another part of the application reads them. For schema changes, plan deployment compatibility and recovery before release.
A rewrite can be justified. A small fix still deserves a clear boundary and evidence that the original problem is gone.
Microsoft's ADO.NET parameter guidance covers parameter names, types and database null values.