Assume I have a page with a data grid bound to a data source. If I have 2 different clients accessing this page, is the data source different for each of them, or do they use the same data source?
If they're the same, what happens if a client applies a filter? The other clients sees that filter too? How to avoid this?
If they're not the same, and I have a big number of records, and data source mode is to DataSet, would this store 2 copies of same data on server? How do I solve such problems?
The SqlDataSource control is an instance class, so it would be recreated on each request. You may want to look into connection pooling though, so you can reuse database connections.
I don't think it's possible to make the control static, and I don't think you need to make the control static. If you want to reuse the dataset for all users who visit the page, I would look into caching the DataSet, or storing it in application state. I believe you can do this with the SqlDataSource using a mixture of the OnSelecting and OnSelected events.
Cache the DataSet in the OnSelected event
In the OnSelecting event, check to see whether you have a cached DataSet, and cancel the the select if you do.
They are separate unless you have made the Dataset static, then it will be shared across all instances of the page. I'm not sure what problem you are trying to solve exactly? Is there no database behind the dataset? Or are you worried about the memory consumption?
Related
I use a lot of ASCX user controls in my projects. These controls utilize update panels to update their contents. To persist data across partial post backs (ie, when update panel updates) I store all the controls data in a session. For example, I might have a control that uses a CheckBoxList. When a user checks a box from the list, it causes a partial postback (to do some logic) and the update panel fires. Because the panel is updating, I would lose all data between post backs, except that I store this data in a session. This way, when the control reloads, I can take the data and restore the checkbox list. My sessions typically consists of lists of objects.
My question is: is this the best way to persist data? What are some possible problems I might not be accounting for? I was told that if multiple people are using this at the same time (as the lists of objects are large) IIS may run out of memory and crash.
Thanks for any help
It's hard to say if this is "the best way to persist data" for your particular project. I can however address the "possible problems" part of your question.
Session state is stored in-memory by default, which means that you will be using additional resources on your server. Session variables can be created on the fly and do not require you to dispose of them explicitly which can lead to more overhead. So yes you are correct that using sessions for much of your functionality will most likely mean using up more resources (CPU and Memory). Whether it will "run out of memory and crash" is a matter of the load vs. the server.
I used bind all GridViews, DetailViews etc. on my page using an ObjectDataSource (unless it wasn't possible to do so). Recently, I've started binding all my contols programatically. I find this a lot cleaner and easier, though some may disagree.
Binding with a ObjectDataSource obviously has it advantages and disadvantages, as does doing it programatically.
Say I bind a GridView programatically (e.g. GridView1.DataSource = SomeList), when I change page on the GridView, I have to also code this. Each time the page changes I have to call GridView1.DataSource = SomeList again. Obviously with a ObjectDataSource I don't need to do this. I normally stick my SomeList object into the ViewState so when I change page I don't need to hit the database each and every time.
My question is: Is this how the ObjectDataSource works? Does it store it's data in the ViewState and not hit the database again unless you call the .Select method? I like to try and get the best performance out of my applications and hit the database as few times as possible but I don't really like the idea of storing a huge list in the ViewState. Is there a better way of doing this? Is caching per user a good idea (or possible)? Shall I just hit the database everytime instead of storing my huge list in the ViewState? Is it sometimes better to hit the database than to use ViewState?
Does it store it's data in the ViewState and not hit the database again unless you call the .Select method?
No its not save the data in ViewState. In the view state gridview and other similar lists, saves the General Status, eg the sort column, the page, the total pages, the control state, but not the Data.
Is caching per user a good idea
The caching per user on server side is not so good idea except if the caching is last for few minutes only or/and the data that you going to cache is very small. If you cache per user large amount of data for long time they going to grow too much especial if a user starts to read a lot of pages, that at the end you have the same problem.
Now you have to show a large amount of data that come from the relation of many tables, then maybe is better to cache the full relation of the tables to "one flat table".
Shall I just hit the database everytime instead of storing my huge list in the ViewState?
This is also depend from how fast you have design the reading of your data. For me is better to keep the ViewState small, and keep there only informations that you need to make the actions on your page, and not data.
I have a web app, that consumes a web service. The main page runs a search - by passing parameters to a particular web service method, and I bind the results to a gridview.
I have implemented sorting and paging on the grid. By putting the datatable that the grid is bound to in the viewstate and then reading / sorting / filtering it as necessary - and rebinding to the grid.
As the amount of data coming back from the web service has increased dramatically, when I try to page/sort etc I receive the following errors.
The connection was reset
The connection to the server was reset while the page was loading.
I have searched around a bit, and it seems that a very large viewstate is to blame for this.
But surely the only other option is to
Limit the results
Stick the datatable in the session rather than the viewstate
Something else I am unaware of
Previously I did have the datatable in the session, as some of this data needed to persist from page to page - (not being posted however so viewstate was not an option). As the amount of data rose and the necessity to persist it was removed, I used the viewstate instead. Thinking this was a better option than the session because of the amount of data the session would have to hold and the number of users using the app.
It appears maybe not.
I thought that when the viewstate got very big, that .net split it over more than one hidden viewstate field, but it seems all I'm getting is one mammoth viewstate that I have trouble viewing in the source.
Can anyone enlighten me as to how to avoid the error I'm getting? If it is indeed to do with the amount of data in the viewstate?
It sounds like your caching the whole dataset for all pages even though you are only presenting one page of that data. I would change your pagination to only require the data for the current page the user is on.
If the query is heavy and you don't want to have to be constantly calling it over and over because there is a lot of paging back and forth (you should test typical useage pattern) then I would implement some type of caching on the web service end to cache page by page (by specific user if the data is specific to a user) and have it expire rather quick (eg a few minuites).
I think you need to limit the total amount of data your dealing with. Change your code to not pass back extra data that might never be needed is a good place to start.
EDIT: Based on your comments:
You can't change the web service
The user can manipulate the query by filtering or sorting
There is a large amount of data returned by the web service
The data is user specific
Well I think you have a perfect case for using the Session then. This can be taxing the the server with large amounts of users and data so you might want to implement some logic to clear the data from the Session and not wait for it to expire (like on certain landing pages you know the user will go when they are done, clear the session data).
You really want to get it out of the ViewState beacuse it is a huge bandwidth hog. Just look at your physical page size and that data is being passed back and forth with every action. Moving it to the Session would eliminate that bandwidth useage and allow for you to do everything you need.
You could also look at the data the web service is bringing back and store it in a custom object that you make as 'thin' as possible. If your storing a DataSet or a DataTable in your Session, those objects have some extra overhead you probably don't need so store the data as an array of some custom thin object and just bind to that. You would need to map the result from the WS to your custom object but this is a good option you cut down on memory useage.
Let me know if there is something else I am missing.
I wouldn't put the data in either the view state or the session. Instead store the bare minimum information to re-request the dataset from the web service and store that (in either view state or session, or even on the URL). Then call the web service using that data and reaction the data on each request. If necessary, look to use some form of caching (memCache) to improve performance.
How would I store the value of a GridView's selected rows to a session variable?
From the codebehind file you will want to use something like this to access the underlying data item (MyDataItem) from the selected row.
MyDataItem item = (MyDataItem)GridView1.Rows[GridView1.SelectedIndex].DataItem;
Session["myItem"] = item;
Remember though, the gridview is already storing this data for you, so you may just want to access it from the GridView directly whenever you need it.
On a side note: can I stronly advise you NOT to use the session state.
Unless you are using it as a store where data is cached for the current user, which you can retrieve back at any time from e.g. a database.
If not, the "session" will come back and bite you. At some point there will be a user that leaves the browser open for longer time than your session lives (e.g. they get a telephone call, go out to lunch in a hurry, rush of to a meeting...). And when they return, they wish to complete what they are doing. And if you cannot restore all of your session data back at that point, you will either have to redirect your user to start over again (very annoying for your users), or you will have lost some information (very embarrasing), or the worst case, and most common case: your application will no longer work and crash (just plain: very bad).
It is a better approach to define small serializable objects that store your state (query parameters, selected items, etc) and use ASP.NET Viewstate to store that state across page requests. Note that most ASP.NET controls already use the viewstate to store their data. Then disable the Viewstate of your grids in the page, to vastly reduce the amount of data in your viewstate, and request the data upon each request (here it is safe to use the session or ASP.NET cache to improve performance of your application). You will have a much more robust and much more scalable application.
It is more work, but it will pay back very fast, and many times over.
ViewState only scope within one page. It's useful for postback problem, but not for cross-page problems. Session can handle both, but it has some limitations of security, lifetime, transmittion time... Depend on particular sittuation you can pick your right choice.
I don't know when to add to a dataset a tableadapter or a query from toolbox. Does it make any difference?
I also dont know where to create instances of the adapters.
Should I do it in the Page_Load?
Should I just do it when I'm going to use it?
Am I opening a new connection when I create a new instance?
This doesn't seem very important, but every time I create a query a little voice on my brain asks me these questions.
Should I just do it when I'm going to use it?
I would recommend that you only retrieve the data when you are going to use it. If you are not going to need it, there is no reason to waste resources by retrieving it in Page_Load. If you are going to need it multiple times throughout the page load, consider saving the query results to a private variable or collection so that the same data can be reused multiple times throughout the page load.
Am I opening a new connection when I create a new instance?
Asp.net handles connection pooling, and opens and closes connections in an efficient way. You shouldn't have to worry about this.
One other thing to consider from a performance perspective is to avoid using Datasets and TableAdapters. In many cases, they add extra overhead into data retrieval that does not exist when using Linq to Sql, Stored Procedures or DataReaders.