我正在将表值参数传递给 StoredProcedure。
请在下面检查我的代码
CREATE TYPE TempTable AS TABLE
(A nvarchar(50), B nvarchar(50), C nvarchar(500))
SqlParameter[] param = new SqlParameter[3];
param[0] = new SqlParameter("@A", A);
param[1] = new SqlParameter("@B", B);
param[2] = new SqlParameter("@C", lstC);
param[2].SqlDbType = SqlDbType.Structured;
param[2].TypeName = "dbo.TempTable ";
DataSet ds = SqlHelper.ExecuteDataset("StoredProcedureName", param);
Run Code Online (Sandbox Code Playgroud)
这里,lstC是类的 List 对象。
但得到错误“ Failed to convert parameter value from a List1 to a IEnumerable1.”
编辑
public static DataSet ExecuteDataset(string spName, params object[] parameterValues)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
if (spName == null || spName.Length == 0) throw new ArgumentNullException("spName");
// If we receive parameter values, we need to figure out where they go
if ((parameterValues != null) && (parameterValues.Length > 0))
{
// Pull the parameters for this stored procedure from the parameter cache (or discover them & populate the cache)
SqlParameter[] commandParameters = SqlHelperParameterCache.GetSpParameterSet(connectionString, spName);
// Assign the provided values to these parameters based on parameter order
AssignParameterValues(commandParameters, parameterValues);
// Call the overload that takes an array of SqlParameters
return ExecuteDataset(CommandType.StoredProcedure, spName, commandParameters);
}
else
{
// Otherwise we can just call the SP without params
return ExecuteDataset(CommandType.StoredProcedure, spName);
}
}
public static DataSet ExecuteDataset(CommandType commandType, string commandText, params SqlParameter[] commandParameters)
{
if (connectionString == null || connectionString.Length == 0) throw new ArgumentNullException("connectionString");
// Create & open a SqlConnection, and dispose of it after we are done
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
// Call the overload that takes a connection in place of the connection string
return ExecuteDataset(connection, commandType, commandText, commandParameters);
}
}
public static DataSet ExecuteDataset(SqlConnection connection, CommandType commandType, String commandText, params SqlParameter[] commandParameters)
{
if (connection == null) throw new ArgumentNullException("connection");
// Create a command and prepare it for execution
SqlCommand cmd = new SqlCommand();
bool mustCloseConnection = false;
PrepareCommand(cmd, connection, (SqlTransaction)null, commandType, commandText, commandParameters, out mustCloseConnection);
// Create the DataAdapter & DataSet
using (SqlDataAdapter da = new SqlDataAdapter(cmd))
{
DataSet ds = new DataSet();
cmd.CommandTimeout = 0;
// Fill the DataSet using default values for DataTable names, etc
da.Fill(ds);
// Detach the SqlParameters from the command object, so they can be used again
cmd.Parameters.Clear();
if (mustCloseConnection)
connection.Close();
// Return the dataset
return ds;
}
}
Run Code Online (Sandbox Code Playgroud)
准备命令
private static void PrepareCommand(SqlCommand command, SqlConnection connection, SqlTransaction transaction, CommandType commandType, string commandText, SqlParameter[] commandParameters, out bool mustCloseConnection)
{
if (command == null) throw new ArgumentNullException("command");
if (commandText == null || commandText.Length == 0) throw new ArgumentNullException("commandText");
// If the provided connection is not open, we will open it
if (connection.State != ConnectionState.Open)
{
mustCloseConnection = true;
connection.Open();
}
else
{
mustCloseConnection = false;
}
// Associate the connection with the command
command.Connection = connection;
// Set the command text (stored procedure name or SQL statement)
command.CommandText = commandText;
// If we were provided a transaction, assign it
if (transaction != null)
{
if (transaction.Connection == null) throw new ArgumentException("The transaction was rollbacked or commited, please provide an open transaction.", "transaction");
command.Transaction = transaction;
}
// Set the command type
command.CommandType = commandType;
// Attach the command parameters if they are provided
if (commandParameters != null)
{
AttachParameters(command, commandParameters);
}
return;
}
Run Code Online (Sandbox Code Playgroud)
在项目更新到 .Net Core 3.1 期间来到这里,并开始在以前工作的代码上收到此错误。如果您要使用 Core 3.1+,这可能仅对您有所帮助
原来这是我在创建结构化数据以发送到我的 sproc 时使用的 SqlDataRecord类型的问题。
旧的:Microsoft.SqlServer.Server.SqlDataRecord
新的:Microsoft.Data.SqlClient.Server.SqlDataRecord
请注意,根据他们对 .Net Core 3.1 及更高版本的建议,我还从 System.Data.SqlClient 转移到了 Microsoft.Data.SqlClient,并在找到开始这篇文章的错误之前清除了另一个错误。
如果您通过参数传递表数据,则需要使用用户定义的表类型,例如:
CREATE TYPE [dbo].[TempTable] AS TABLE(
[A] [varchar](50) NULL,
[B] [varchar](50) NULL,
[C] [varchar](500) NULL,
)
Run Code Online (Sandbox Code Playgroud)
并且lstC应该是一个DataTableorIEnumerable<SqlDataRecord>而不仅仅是您自己的类的列表。
尝试:
param[2] = new SqlParameter("@C", lstC.Select(c => c.ToSqlDataRecord()));
Run Code Online (Sandbox Code Playgroud)
ToSqlDataRecord你的类中的辅助函数在哪里?例子:
public class Thing {
public string A { get; set; }
public string B { get; set; }
public string C { get; set; }
// to match the dbo.TempTable User-Defined Table Type on database
private static readonly SqlMetaData[] myRecordSchema = {
new SqlMetaData("A", SqlDbType.VarChar, 50),
new SqlMetaData("B", SqlDbType.VarChar, 50),
new SqlMetaData("C", SqlDbType.VarChar, 500)
};
public SqlDataRecord ToSqlDataRecord() {
var record = new SqlDataRecord(myRecordSchema);
record.SetString(0, A);
record.SetDateTime(1, B);
record.SetDateTime(2, C);
return record;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15307 次 |
| 最近记录: |