LINQ to SQL did a horrible job translating one of my queries, so I rewrote it by hand. The problem is that the rewrite necessarily involves an IN
clause, and I cannot for the life of me figure out how to pass a collection to ExecuteQuery
for that purpose. The only thing I can come up with, which I've seen suggested on here, is to use string.Format
on the entire query string to kluge around it—but that will prevent the query from ever ending up in the query cache.
What's the right way to do this?
NOTE: Please note that I am using raw SQL passed to ExecuteQuery
. I said that in the very first sentence. Telling me to use Contains
is not helpful, unless you know a way to mix Contains
with raw SQL.
On Cheezburger.com, we often need to pass a list of AssetIDs or UserIDs into a stored procedure or database query.
One way to pass this list in was to use dynamic SQL.
IEnumerable<long> assetIDs = GetAssetIDs(); var myQuery = "SELECT Name FROM Asset WHERE AssetID IN (" + assetIDs.Join(",") + ")"; return Config.GetDatabase().ExecEnumerableSql(dr=>dr.GetString("Name"), myQuery);
This is a very bad thing to do:
';DROP TABLE Asset;SELECT '
and our site is dead.However, it does have the advantage that no additional decoding is necessary on the DB side, since the AssetIDs are found by the query parser.
SQL Server 2008 adds a new ability: users can define a table-valued database type. Most other types are scalar (they only return one value), but table-valued types can hold multiple values, as long as the values are tabular.
We've defined three types: varchar_array
, int_array
, and bigint_array
.
CREATE TYPE bigint_array AS TABLE (Id bigint NOT NULL PRIMARY KEY)
Both stored procedures and programmatically defined SQL queries can use these table-valued types.
IEnumerable<long> assetIDs = GetAssetIDs(); return Config.GetDatabase().ExecEnumerableSql(dr=>dr.GetString("Name"), "SELECT Name FROM Asset WHERE AssetID IN (SELECT Id FROM @AssetIDs)", new Parameter("@AssetIDs", assetIDs));
Advantages
Disadvantages
This article is a great resource to learn more about TVP.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With