Is it safe method for C# against sql injection?
if sNumber
actually was a numeric type, like int or decimal then I'd say "maybe" because it's pretty hard to inject SQL into a number, but at the end of the day, all you've done is change from concatenating a string value directly into an sql query, which is the classic fail:
"SELECT * FROM t WHERE x = " + str
into putting a string value into a db variable that you then use in an sql. It means the select query won't be the place where the injecting is done, but it just moves the injection point earlier:
Think what happens when sNumber
is a value like '; DROP TABLE students;--
DECLARE @number nvarchar(MAX) SET @number = '%';
DROP TABLE Students;--%'
SELECT ...
If you truly are restricted to using this function (it needs throwing away, tbh) then you'll have to do your best at preventing injection by sanitizing the input. In this case you say you're expecting a document number like 2-12
so your C# should look like
if(!Regex.IsMatch(userInput, @"^\d+-\d+$"))
throw new ArgumentException("Bad input value, expecting document number like 2-12");
var dt = Execute4Table($"SELECT * FROM t WHERE x = '{input}');
In a general sense, it would be clunky, but you could perhaps do some wrapper function that takes N parameters and serializes them to JSON, then you pass them to sqlserver as a json string and get SQLS to deser them into N parameters that you use in the query. The two serializers should encode any user provided values in such a way that they are interpreted as data rather than code. You could also do a similar thing with base64 if your sqlserver is too old for json. To some extents this isn't much different to replacing all ' with '' but with a set/deser approach you're handing off responsibility for that encoding to a well tested library, which is probably the only thing you can do if you are rather hamstrung by this method you're forced to use