I think you can try these two ways: 
- Without a stored procedure: You can try with SqlBulkCopy class.
C# Code:
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;
    }
- With a stored procedure: Try with a table-valued parameter
SQL Code:
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# Code:
    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();
            }
        }
    }