在实现表值参数时,生成供该参数使用的IEnumerable<SqlDataRecord>
的最常见方法之一就是这样的代码(例如https://stackoverflow.com/a/10779567/18192):
public static IEnumerable<SqlDataRecord> Rows(List<int> simpletable)
{
var smd = new []{ new SqlMetaData("id", SqlDbType.Int)};
var sqlRow = new SqlDataRecord(smd);
foreach (int i in simpletable)
{
sqlRow.SetInt32(0, i);
yield return sqlRow;
}
}
//...
var param = sqlCmd.Parameters.AddWithValue("@retailerIDs", Rows(mydata));
param.SqlDbType = SqlDbType.Structured;
param.TypeName = "myTypeName";
这段代码似乎确实有效。虽然重用
SqlMetaData
不会引起太多警钟,但在SqlDataRecord
循环之外声明 foreach
对我来说令人难以置信:可变对象被修改,然后反复产生。
例如,在LinqPad中调用
var x = Rows(new[] { 100, 200}.ToList()).ToList().Dump()
会吐出200,200
。这种方法似乎依赖于实现细节(行是单独处理的),但是我看不到任何有保证的文档。是否有一些缓解因素可以使此方法安全?
最佳答案
正如user1249190所指出的,在https://docs.microsoft.com/en-us/dotnet/api/microsoft.sqlserver.server.sqldatarecord#remarks的备注部分中明确建议重用SQLDataRecord:
显然,此建议不适用于跨线程使用:文档还明确警告:“不保证任何实例成员都是线程安全的”。
关于c# - 重用SqlDataRecord是否安全?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/37007018/