Domanda

I am writing a program in C# that runs some select statements using parameters passed to sp_executesql. One issue that I'm running into when testing is that, whether I get the the commands executed from SQL Profiler or from a watch in Visual Studio, the values of the parameters are specified at the end of statement rather than being explicitly specified in-line in the query. For testing purposes, I would like a quick way to substitute the parameter values for the parameters.

So, instead of:

exec sp_executesql N'
SELECT CustomerName
FROM CustomerTable ct WITH(NOLOCK)
WHERE ct.CustomerId <> @CustomerId
AND ct.ItemId <> @ItemId
AND ct.TransactionId = @TransactionId'
,N'@CustomerId bigint,@ItemId nvarchar(1),@TransactionId nvarchar(30), @CustomerId = 3000, @ItemId = N'4', @TransactionId=N'43281'

I want:

exec sp_executesql N'
SELECT CustomerName
FROM CustomerTable ct WITH(NOLOCK)
WHERE ct.CustomerId = 3000
AND ct.ItemId <> N'4'
AND ct.TransactionId = N'43281''

Please don't pay too much attention to the syntax of the example, since it is just being used to demonstrate the concept. Does anyone know a fast way to do this? Basically, I would like to have it substituted for testing purposes, as it will make it easier for me to modify conditions to test how they affect the results returned. I would appreciate any help anyone can give. Thanks.

È stato utile?

Soluzione

Parameterized sp_executesql has many benefits, including

  • By explicit parameterizing you are giving the chance for SQL to cache decent query plans on definite types
  • By parameterizing it helps prevent nasties like SQL injection attacks, but also avoids the need to escape problematic characters.

So even if you do manage to 'unparameterize' the generated sp_executesql, if you execute the inline sql, the query plan could be significantly different to the parameterized version, and you would also need to do escaping etc (i.e. it wouldn't be suitable for apples vs apples testing).

The only reason I can think of why you wouldn't want parameterized sp_executesql would be for ease of readability?

Edit: Trying to substitute would be dependent on what technology you are using

As @mellamokb suggested, if you are using ExecuteReader this could be quite straightforward

Assuming your code was something like

string sqlCmd = "SELECT CustomerName 
FROM CustomerTable ct WITH(NOLOCK) 
WHERE ct.CustomerId <> @CustomerId 
AND ct.ItemId <> @ItemId 
AND ct.TransactionId = @TransactionId";

cmd.CommandText = sqlCmd;
cmd.CommandType = CommandType.Text;
cmd.Parameters.Add(new SqlParameter("CustomerId", DbType.Int32, myCustomerId));
cmd.Parameters.Add(new SqlParameter("ItemId", DbType.String, myItemId));
..
cmd.ExecuteReader()

You could then add code to build your test query:

string sqlMyTest = sqlCmd.Replace("@CustomerId", myCustomerId.ToString());
sqlMyTest = sqlMyTest.Replace("@ItemId", specialEscapeFunction(myItemId));
.. do something with sqlMyTest

However an ORM like Linq2SQL or EF would not be as easy

customerTable.Where(c => (c.CustomerId != myCustomerId) && (c.ItemId != myItemId) && (c.TransactionId == myTransactionId))

Possibly a tool like LinqPad might help?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top