Is there a way to detect if string concatenation have been used?

In our datalayer, I want to discourage the use of string concatenation and make people use parameters instead.

But as far as I know, there is no way to see if a parameter is a concatenated string.

I have no code example to show of detection, since I know of none.

var result = db.executeQuery("SELECT * FROM table WHERE id = " + id);

This is the kind of code I'd like to get rid of, either to replace with something like:

db.executeQuery($"SELECT * FROM table WHERE id = {id}");

or

db.executeQuery("SELECT * FROM table WHERE id = {0}", id);

Edit:

The command executeQuery is in our datalayer and handles parameters as SqlParameters, with types and values.

So in this case a SqlParameter called @id with type int would be created.

Regarding the FormattableString:

public T ExecuteObject<T>(FormattableString sql)
{
    return executeSingleRow(sql.Format, sql.GetArguments()).ToType<T>();
}

Regarding the ExecuteQuery:

public int executeNonQuery(string sql, params object[] parameters)
{
    var traceI = Traceadd(sql, parameters);
    if (!open())
        throw new Exception("Error executing query!", lastException);

    try
    {
        command = Connection.CreateCommand();
        command.CommandText = sql;
        sql.SQLFormat(ref command, parameters);
        var res = command.ExecuteNonQuery();
        command.Parameters.Clear();

        if (traceI != null)
            traceI.Stop();

        return res;
    }
    catch (Exception ex)
    {
        if (traceI != null)
            traceI.Stop();

        throw new DBException(command.CommandText, command.Parameters, ex);
    }
}
Jon Skeet
people
quotationmark

If your executeQuery method only has a parameter of FormattableString, then you should be fine already - there's no conversion from string to FormattableString. For example:

using System;

class Program
{
    static void Main(string[] args)
    {
        int id = 10;
        ExecuteQuery("SELECT * FROM table WHERE id = " + id);
    }

    static void ExecuteQuery(FormattableString query)
    {
    }
}

That gives an error:

Test.cs(8,22): error CS1503: Argument 1: cannot convert from 'string' to 'System.FormattableString'

You just need to make sure that you don't have an overload of your method accepting string. The result of string concatenation is never a FormattableString. Indeed, I would strongly advise that you avoid ever overloading a method to accept FormattableString and string... there's no point in doing so if you're not going to change the behaviour, and if you are going to change the behaviour, that could be really confusing.

I'd personally consider changing to use an extension method on FormattableString though - something like:

public static SqlCommand ToCommand(
    this FormattableString query,
    SqlConnection connection)
{
    // ...
}

That way you can separate the command creation from the execution... which means (aside from anything else) that you can then call ExecuteReader or ExecuteNonQuery without having any extra code yourself.

people

See more on this question at Stackoverflow