This seems like a case of block execution. Often we have to process many records in a routine and several developers reuse the business layer (java or c #) for this, but, experience shows that you will end up compensating on hardware implementation or suffering to optimize code and bank trying to win milliseconds changing small snippets of code, when in fact much of the time spent in routine is spent on network traffic, opening connections, and managing batch execution.
The definitive solution to this does not exist, it will depend a lot on your long-term view of the system and the size of the records and processing actions you perform as well as the architecture of your system.
If you do not want to stick to the layers and you really want to make sure that the business rules are always in the coding (c #, java, c ++ etc) then you're going to have a little trouble to gain performance.
A simple alternative is to reassess if you really need to pass the list of parameters that is the result of the filter, when you can simply pass the filter and operate the select on the bank.
One advantage of this is that you will only use a few parameters running through the network (faster) and since you will not have to break the list, you will only go to the bank once.
Another alternative is to serialize into a string and pass the parameters you need, I think, if you select that data and a filter, you can pass filter values to a procedure is faster and easier. p>
Even if you perform batch processing with the data that is passed (the many records) you could either do this in the procedure that receives the parameters or create a scheduling form based on the filters to process the records in a job .
Avoiding locking the user's screen expecting responses from the transaction.