As suggested in the comments, interpolated strings are turned into typed parameters, so if you run SQL Profiler, I expect what you'll see actually being run is:
WHERE name = '@p0' AND object_id = OBJECT_ID('@p1.@p2') AND is_unique_constraint = 0
A simple test case for this is:
var stringIn = "test";
var query1 = context.Database.SqlQuery<string>($"SELECT '{stringIn}' AS Value").SingleOrDefault();
Console.WriteLine($"Query 1: {query1}");
var query2 = context.Database.SqlQuery<string>($"SELECT {stringIn} AS Value").SingleOrDefault();
Console.WriteLine($"Query 2: {query2}");
var query3 = context.Database.SqlQuery<string>($"SELECT Value FROM (VALUES ('test')) AS x (Value) WHERE Value = '{stringIn}'").SingleOrDefault();
Console.WriteLine($"Query 2: {query3 ?? "Null"}");
var query4 = context.Database.SqlQuery<string>($"SELECT Value FROM (VALUES ('test')) AS x (Value) WHERE Value = {stringIn}").SingleOrDefault();
Console.WriteLine($"Query 4: {query4 ?? "Null"}");
OUTPUT
Query 1: @p0 //Literal string for parameter name
Query 2: test //Actual parameter value
Query 2: Null // No results because "Test" != "@p0"
Query 4: test //Result returned because "Test" = "Test"
Finally, getting SingleOrDefault()
then checking for null could be simplified a bit by using Any()
.
So all in all this should work for you:
return context.Database.SqlQuery<int?>($"SELECT 1 as Value FROM sys.indexes WHERE name = {indexName} AND object_id = OBJECT_ID(CONCAT(QUOTENAME({schema}), '.', QUOTENAME({table}))) AND is_unique_constraint = 0").Any();
ADDENDUM
To address the comments, the likely reason you get an error without quotes is because it was creating malformed SQL:
object_id = OBJECT_ID(@p1.@p2)
This is why in the above I've used CONCAT()
(along with QUOTENAME()
) to build the object name, ending up with something like:
object_id = OBJECT_ID(CONCAT(QUOTENAME(@p1), '.', QUOTENAME(@p2)))