如何将数组作为参数传递给存储过程?

时间:2017-10-23 22:30:29

标签: c# arrays sql-server parameters

我正在尝试从C#发送一个字符串到SQL服务器,但我不知道如何使用存储过程将该字符串插入另一个表。

我想要插入数据的表只有2列,@ IDUser(我也是从C#传递的参数,对于所有idproduct都是相同的)和@IDProduct字符串,它将类似于" 1,2,3,4"

所以我想要的是一个存储过程来单独插入@idUser和数组值,如

SELECT t.grp_id,
       t.min_value,
       t.max_value,
       price_min.value first_value,
       price_max.value last_value
FROM (
  SELECT   FROM_UNIXTIME(28*60 * (UNIX_TIMESTAMP(created) DIV (28*60))) grp_id
           MIN(value)    min_value,
           MAX(value)    max_value,
           MIN(created)  min_created,
           MAX(created)  max_created
  FROM     price
  GROUP BY grp_id
) t JOIN price price_min ON price_min.created = t.min_created
    JOIN price price_max ON price_max.created = t.max_created

我正在使用sql server 2016。

我找到了这个问题的可能答案,但与我的SQL Server知识水平相比,它们看起来非常复杂。

感谢

1 个答案:

答案 0 :(得分:4)

我认为你可以试试这两种方式:

  1. 没有存储过程:您可以尝试使用SqlBulkCopy类。
  2. C#代码:

    static void Main(string[] args)
        {
            Console.WriteLine("Inserting ...");
    
            var userId = 777;
            var productIds = new List<int> { 1, 2, 3, 4 };
            var dto = new Dictionary<int, List<int>>
            {
                { userId, productIds }
            };
    
            ExecuteBulkInsert(dto);
            // ExecuteProcedure(dto);
    
            Console.WriteLine("Done! ...");
            Console.ReadLine();
        }
    
        public static void ExecuteBulkInsert( Dictionary<int, List<int>> dto)
        {
            string connectionString = GetConnectionString();
    
            using (SqlConnection connection = new SqlConnection(connectionString))
            {
                connection.Open();
                DataTable newProducts = CreateDataTable(dto);
    
                using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connection))
                {
                    bulkCopy.DestinationTableName = "dbo.UserProducts";
                    bulkCopy.WriteToServer(newProducts);
                }
            }
        }
    
        private static DataTable CreateDataTable(Dictionary<int, List<int>> dto)
        {
            const string IdUserColumnName = "IdUser";
            const string IdProductColumnName = "IdProduct";
    
            DataTable table = new DataTable();
            table.Columns.Add(new DataColumn(IdUserColumnName, typeof(int)));
            table.Columns.Add(new DataColumn(IdProductColumnName, typeof(int)));
    
            foreach (var product in dto)
            {
                foreach (var productId in product.Value)
                    table.Rows.Add(product.Key, productId);
            }
    
            return table;
        }
    
    1. 使用存储过程:尝试使用table-valued parameter
    2. SQL代码:

      CREATE TABLE dbo.UserProducts
      (
          IdUser INT NOT NULL,
          IdProduct INT NOT NULL
      );
      GO
      
      CREATE TYPE dbo.UserProductsType AS TABLE
      (
          IdUser INT NOT NULL,
          IdUser INT NOT NULL
      );
      GO
      
      CREATE PROCEDURE dbo.UserProductsInsert
          @userProductsType dbo.UserProductsType READONLY
      AS
      BEGIN
      
          INSERT INTO UserProducts
          SELECT * FROM @userProductsType 
      END
      

      C#代码:

          private static void ExecuteProcedure( Dictionary<int, List<int>> dto)
          {
              string connectionString = GetConnectionString();
      
              using (SqlConnection connection = new SqlConnection(connectionString))
              {
                  connection.Open();
                  using (SqlCommand command = connection.CreateCommand())
                  {
                      command.CommandText = "dbo.UserProductsInsert";
                      command.CommandType = CommandType.StoredProcedure;
      
                      SqlParameter parameter = command.Parameters.AddWithValue("@userProductsType", CreateDataTable(dto));
                      parameter.SqlDbType = SqlDbType.Structured;
                      parameter.TypeName = "dbo.UserProductsType";
      
                      command.ExecuteNonQuery();
                  }
              }
          }