Join Sara Morgan for an in-depth discussion in this video What is the StandardSetController?, part of Improving Visualforce Performance.
- When working with a single record from an SObject you can use the standard controller, such as the page you see here, which is used to display the detail for a single account record. If you are accessing multiple records then you can use the built in standard list controllers to get access to basic pagination and filtering features. All you need to do is add the recordSetVar attribute to your page tag, such as in this example, and off you go. What you may not be aware of is that the standard list controller is actually based on the StandardSetController class and that you can reference this class in your own custom controllers.
And now you may be asking, "Why might I want to do that?" To answer that question let's look at what is a StandardSetController. As I said earlier, all standard list controllers are based on this class, but the force.com platform allows you to extend this class for use in your own custom controllers, which is good because the standard list controller, even using a SQL offset clause, is limited to no more than 2,000 records. If you are working with very large datasets then you can go past this limit by using the StandardSetController and have the capacity to paginate over as many as 10,000 records.
Additionally, when working with large datasets, the StandardSetController really is the way to go since it stores dataset on the server, which reduces page state and helps to increase performance. It is designed to work efficiently with lots of data. I'm going to go ahead and switch back over to my browser and go to the main Accounts page that's used to display all the accounts in my org, and click the View to get all accounts. And even though I've loaded up my org with 5,000 accounts you'll see that down at the bottom I'm only getting back a list of one through 25 of 2,000 records.
Even if I were to page through all of this to the very end I would never get past this 2,000 record limit. And the reason for this is because the built in Salesforce list page utilizes that standard list controller, which is limited to 2,000 records. Even if I were to go back to that account search page that I introduced to you in chapter two and use a special SQL clause known as SQL offset I would still be limited to that 2,000 record limit.
As it is now, if I do a search for all accounts that start with the letter A, because I have so many records in my org I get back a pretty long list here, and if I'm scrolling through all of this you can see that it takes quite a lot of scrolling. Most users are not going to have the tolerance for this. So a much better design would be to add pagination to this. To get past that 2,000 record limit and also take advantage of the efficiency, such as pagination and the way it returns view state offered by the StandardSetController, I'm going to have to make a few changes to the controller for this page.
And I'm going to walk you through those changes. The first change is going to be to add a public variable of type ApexPages.StandardSetController. And I'm going to name that set C-O-N for standard controller. And use the standard get and set methods. And now I'm going to go down into the search method and instead of returning my SQL into a list of accounts, that acc variable, I'm going to instead return it into this set controller, but I'm going to have to use the new keyword to instantiate it, and create a variable of ApexPages type StandardSetController.
Open parentheses, and use Database.getQueryLocator to return that data into my set controller using the same SQL statement that I had earlier. I'll just need to add the closing parentheses. And now at this point I've returned my variable, my data, into my set controller, but my page is still referencing that acc variable with the List of Account data.
So in order to get it into that I'm also going to have to modify the standard get I have up here in my list of accounts. And what I'm going to do is go ahead and replace that. And I'm going to use an if statement to avoid an error and check to see that that set controller variable is not equal to null, because if it is I'm going to want to return null, but instead I'm going to return that set controller variable and use getRecords to get all the records associated with it.
But since I'm returning it into a list of accounts I'm also going to have to specify that type here. So I'm going to have a List of Account. And then I'll close out that if statement. And do an else for if it is null, and if it is go ahead and return null.
Then just close all this out. And if I were to click save at this point I will get an error that says that the method cannot be marked transient at line one. The reason for that is because I can't use the Transient variable when overriding that get method. But I'm really not going to need that at this point because of the fact that I'm using the StandardSetController and it's so much more efficient. So I'm going to remove that Transient variable, and then save my page. And now I'm able to compile.
And if I were to go back and do a search for all accounts that start with A you'll see that my results are actually only 20 records that I have here. The reason for that is because by default the StandardSetController will only return a page size of 20 records. We can change that by exposing a variable that lets the user select that page size, but the biggest thing I wanted to point out is that if you look at my View State now that it's much smaller than when I was using the same page using the standard list controller to return all of the accounts and not using the StandardSetController.
So automatically I've already reduced that page state even though I'm not using the Transient variable anymore. If you'd like to learn more about the different pagination options available in the force.com platform you can refer to this excellent article on Developerforce which you can find at the URL you see here.
- Reducing and eliminating view states
- Evaluating SOQL for efficiency
- Using Workbench and the Query Plan tool to evaluate queries
- Reducing use of action tags through Visualforce remoting
- Working with the StandardSetController class
- Using static resources