日志含义将参数值从List ' 1转换为IEnumerable ' 1失败

本文关键字:失败 IEnumerable 转换 List 参数 日志 | 更新日期: 2023-09-27 17:50:18

我正在传递表值参数给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);

这里,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;
        }
    }

准备命令

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;
    }

日志含义将参数值从List ' 1转换为IEnumerable ' 1失败

在。net Core 3.1的项目更新期间来到这里,并开始在以前工作的代码中出现此错误。这可能只有在你要使用Core 3.1+

时才有用。

原来这是一个问题与类型的SqlDataRecord 我在创建结构化数据发送到我的程序时使用。

old: Microsoft.SqlServer.Server.SqlDataRecord
new: Microsoft.Data.SqlClient.Server.SqlDataRecord

注意,我也已经从System.Data.SqlClient转移到Microsoft.Data.SqlClient基于他们的建议。net Core 3.1和更高版本,并在找到开始这篇文章的错误之前清除另一个错误。

如果你通过参数传递表数据,你需要使用用户定义的表类型,例如:

CREATE TYPE [dbo].[TempTable] AS TABLE(
    [A] [varchar](50) NULL,
    [B] [varchar](50) NULL,
    [C] [varchar](500) NULL,
)

lstC应该是DataTableIEnumerable<SqlDataRecord>,而不仅仅是你自己的类列表。

试题:

param[2] = new SqlParameter("@C", lstC.Select(c => c.ToSqlDataRecord()));

其中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;
    }
}