How to save Dataset in temp memory of page? - asp.net

I have a function which call a procedure from SQL Server and return a datatable as
public static DataTable GetProducts(int parmCategory = -1){}
in my asp page I have
ReportViewer1.LocalReport.DataSources.Add(new ReportDataSource("DataSet1", ReportsBLL.GetProducts()));
ReportViewer1.LocalReport.Refresh();
which fill once in pageload()
this procudure takes about 8 minutes to get data from database
and I want to make a lot of filtration in button press to filter data which comes from GetProducts
and there is no logic to call procure in every filter and contact the DB
So, how can I save the data once I get it in the pageload and deal with it in button press filtration

It depends on how much data is returning.
If its not too much, put the data into the session variable with something like this:
Set the data into a variable on page called dataSet1.
Session["DataSet1"] = dataSet1;
If the data is massive, you really want to consider having the page "refresh" between filtering. This way you don't blow out your memory.

Related

Dynamics AX 2012 - Grid Control linkPhysicalTableInstance to TempTable, first record inserted doesn't appear in Grid, fine afterwards

The problem related to using table buffers in AX 2012 with Grid Controls, where first time additions to the form's tempDB were not displayed in real time (but were persistent and subsequent additions worked fine thereafter).
I resolved the problem with help from DAX legend Martin Dráb and Brandon Weise on the Dynamics Community MSDN but I'm posting on SO in case it helps others (as I couldn't find anything close), and I don’t think it hurts the community to add more Dynamics AX content on SO. There are also some learnings to be had about how physical tables link to tempDBs and their relationship to the form's datasource.
Original thread: https://community.dynamics.com/ax/f/33/t/225120
Problem:
I have a Wizard that generates a new form at runtime, containing a Grid Control.
The Wizard passes a reference to one of its temp Tables to the form, in which I use linkPhysicalTableInstance in the runtime form's datasource init() method.
The GridControl has an add new record button, which inserts records in to the tmp table reference.
The new record is saved to the reference temp table correctly, and displays in the grid when the runtime form is closed and reopened but does not display in the grid immediately after the insert.
To add to the weirdness, after a runtime form has been created, a record inserted and then closed, subsequent run time forms do display new record insertions immediately, without needing to be re-opened. Some code snippets below.
Why does this behavior only happen for the first time that data is inserted in to the temp table, but displays fine for subsequent runs of the runtime form?
Creating the runtime form:
args = new Args(formstr(RunTimeFormName));
formRun = classFactory.formRunClass(args);
formRun .parmRuntimeFormsGridTmpDS(sysWizard.ReferenceToWizardsTableTmp()); // Passing a reference for Wizards tmpTable to form
formRun .init();
formRun .run();
formRun .wait();
formRun .detach();
RunTime Form's parmDataSourceMethod:
public void parmRuntimeFormsGridTmpDS(CommentsGridTmp _ReferenceToWizardsTableTmp)
{
ReferenceToWizardsTableTmp = _ReferenceToWizardsTableTmp;
}
DataSource init() method:
public void init()
{
super();
RuntimeFormsGridTmpDS.linkPhysicalTableInstance(ReferenceToWizardsTableTmp);
}
RunTime Form's New button clicked method:
void clicked()
{
int64 numRows;
;
// Refresh records loaded in grid DS to ensure correct number of records for setting initial index number
// Note: SomeId is passed in Args() record, its passing fine as is the number of rows count - and replacing with a static value has no effect.
select count(RecId) from ReferenceToWizardsTableTmp
where ReferenceToWizardsTableTmp.SomeId == someId;
numRows = ReferenceToWizardsTableTmp.RecId;
ReferenceToWizardsTableTmp.Comment = "Comment " + int642str(numRows + 1);
ReferenceToWizardsTableTmp.Filename = "";
ReferenceToWizardsTableTmp.someId = someId;
ReferenceToWizardsTableTmp.insert();
element .Task(#TaskF5);
// super();
}
So as described above, the first time that the runtime form is created and a record is inserted, it doesn't display. Reopening the form will display the inserted data fine. Also, after reopening the form any new records inserted appear in the grid in real time.
I originally supposed it had to be something to do with the linkToPhysicalTable and where the grid fields look for records to display…
By the way, if you have a better answer or explanation then please feel free to contribute.
Solution
I have a working solution whereby I run a select statement on the buffer reference prior to the linkPhysicalTableInstance operation (a delete_from tmptable statement has the same effect and is cheaper), which acts to initialize the buffer reference despite it being empty.
The linkPhysicalTableInstance operation then succeeds at the first run because the buffer properly exists - and changes written to the form DS are now persistent and reflected in the calling Wizard's buffer reference.
In Addition (from Brandon Weise):
In case you happen to be jumping tiers in your code, here's a small gotcha to watch out for.
https://community.dynamics.com/ax/b/dynamicsaxexperience/archive/2016/01/24/2012-unexpected-degeneration-of-insert-recordset-into-tempdb-buffer
Techniques That I Found Useful for Investigation
(Credit to Brandon Weise and Martin Dráb for these)
It does seem that using .linkPhysicalTableInstance(..) to change the underlying temp table associated with a form datasource after it
has already initialized produces some weird behavior. This seems to
be true even when you can demonstrate with .getPhysicalTableName()
that they are linked properly.
One technique to help is to create your form, and
call .init(), but not yet .run(). Then use
.linkPhysicalTableInstance() to link the freshly created temp table
underlying the data source to your external temp table buffer. In
other words, instead of trying to transplant your already created
temp table into the form's data source, let the form create the temp
table, then let the caller transplant that temp table into its own
buffer using .linkPhysicalTableInstance(). Then insert records,
then call .run(). If necessary, call .executeQuery() on the form
data source after .run().
I took a scattergun approach to printing
the table names throughout initialization and operation, and while
the two tables do eventually link correctly with the same table
name, they take a roundabout way of getting there.
Inspect the contents of a temp table while debugging, from SQL Server Management Studio using:
set transaction isolation level read uncommitted;
select * from tempdb..t107946_BE044A13A9C24283897CA1B59607CBD2;
Which is easy if you have the table name from
.getPhysicalTableName(), but even if you don't know it precisely,
it's often easy to locate with a little trial and error. select *
from tempdb.sys.tables; The table will of course start with "t" and
the table number. Often it's the most recently created one, so
sorting by create_date desc floats it to the top, but of course
there can be a pool of them.
Review Methods on a Form Data Source which methods you can use when working with records through a datasource.

How to send data gridview values from one page to another

i want to send grid view data from one page to another without using database.
i am taking some inputs from user, storing and displaying in gridview. now i want to send same data gridview values to another page on click of button.
what will be the best possible way to do this.
Yous data not lives on GridView, but on the database, or on session, or on a file.
The GridView only shows them, not store them ! Even if you see them there, is actually on the html page on the client side, and they are not even post back.
So what you need to move to the next page is the "pointer" to the data, and reads them base on this "pointer"
You may have a simple List<> on the session, or an id and reads them from the database.
The solution is to saves your user input data somewhere - from what I understand the session for you can be a fast easy solution, and take them back on the next page.
put the gridview data into datatable
then put the datatable into session as shown:
DataTable tb= new DataTable();
Session["dt"] = tb;
on the next page, to read session value:
DataTable dt = new DataTable();
dt = (DataTable)Session["dt"];
to bind gridview data to datatable, check this link:
Putting GridView data in a DataTable
hope it helped :)

ASP.Net - Using variable value in different button click events - VB

I have a multiview with 4 views. To switch between the views I use 4 buttons and switch the multiview's activeview index to the relevant view inside the click event of each button.
In each view there are various controls to capture data. There is then a submit button at the bottom of the final view to write all the data to a database.
What I want to achieve is to capture a time stamp of when the user clicks the button to move to each view (which will ultimately be written to the database). I can assign a timestamp to a variable by using the below code in the click event of each of the 4 buttons
Dim phase1TimeStamp as string = DateTime.Now.TimeOfDay.ToString()
The problem is, when I come to write the records to the database in the click event of the submit button, it cannot see the values assigned to these time stamp variables.
Is there a way I can pass these variable values to the submit button click event or is there a different way I can achieve this altogether? Thanks
The easiest way to do this is probably by saving the variable to session, then retrieving it. You didn't say if this was ASP .NET Web Forms or MVC, so I will give you an option for each. MVC has a few different ways you can achieve this (ViewData, ViewBag, TempData, or directly to Session). I'm not quite as familiar with Web Forms but you can at least save to Session.
Web Forms
to save to session:
HttpContext.Current.Session("phase1TimeStamp") = phase1TimeStamp.ToString()
to retrieve it (you may have to cast it, depending on the type and your VB settings):
Dim myVar as String = HttpContext.Current.Session("phase1TimeStamp")
MVC
to save to session:
Session("phase1TimeStamp") = phase1TimeStamp.ToString()
to retrieve it:
Dim myVar as String = Session("phase1TimeStamp")
A note about MVC: If you want this to work across multiple sessions (I.E., for different users or even for the same user but with multiple tabs open), you will need to append the identifier ("phase1TimeStamp") in this case with some sort of unique identifier.
You can store the values in Session cache, like this:
Session("MultiView1_Clicked_DateTime") = DateTime.Now.TimeOfDay.ToString()
Session("MultiView2_Clicked_DateTime") = DateTime.Now.TimeOfDay.ToString()
Session("MultiView3_Clicked_DateTime") = DateTime.Now.TimeOfDay.ToString()
Session("MultiView4_Clicked_DateTime") = DateTime.Now.TimeOfDay.ToString()
The Session value will exist in memory across page requests.
Note: You can name the Session key whatever you wish, but to get the value back out you need to match that key name exactly. Also, everything in Session is stored as an Object so you will need to cast the value to a String when you want to retrieve the value.

page load taking much time asp.net

I have a user control that fetches data from a database. It takes a lot of time. Also the speed of my web application has become slow. What should I do to make page loading faster?
I will answer in general way.
If you only fetches data with out calculations, then:
DataBase Part
a. Optimize your sql query, be sure that you use the right indexes on database.
b. Do not load more than the data that you won to show, and do paging.
c. If you fetch data from too many tables at the same time, create a new 'flat' table, and pre render your results there on a scheduled regular base on a background thread.
Page Part
a. While you load data, show them imidiatle and do not buffer them, and time to time make a flush to the responce.
If you fetche data with calculations, then make the calculations on a background thread before you show them on a scheduled base, place them on one other flat table, and show that table.
For example, how to show the data while you get them....
<%
int KathePoteFlush = 1;
object Data;
While(GetNextData(Data))
{
if (20 % KathePoteFlush++ == 0)
Response.Flush();
Response.Write(RenderMyTableData(....data....));
};
%>

Is it possible to convert this asp to asp.net?

I have been tasked with sifting through the worst classic asp spaghetti i've ever come across.
The script runs a series of recordsets in sequence, getting 1 record at a time. As the record is built it takes the id and passes it to the next loop, which gets data, and passes on the id to the next loop. It then continues in this manner and builds an unordered list, kicking out the required html as it goes.
Here are my efforts so far:
have a class delivering data via sqldatareaders and output these to nested repeaters (this failed due to not being able to loop and get the id)
Have a datatable populated with all the required data, then datatable.select to filter it out.
have 4 datareaders looping and building the ul arraylists (I
couldnt get the id's to match up)
Please can you suggest the best method
Yes of course it can be rewritten in ASP.NET - note that i said rewritten, not just refactored, there is no saving that code (which is okay for what it does, but things are different with ASP.NET).
To be honest, i didn't even check the code, it hurt my eyes. A lot. But in general you can use a nice SQLConnection object, and a SQLCommand, call a stored procedure and get a nice SqlDataReader full of data from which you can build a DataTable or an IEnumerable list of data objects. You then have a repeater type control (ListView, GridView etc) in the UI, simply by binding your datatable or list to that control will render the results.
With the ListView, you specify a template for each data item that is rendered. For a GridView you specify the columns (or column templates) and which properties on each data item the columns should bind to.
When you retrieve the data, you can leave it as a DataTable, or translate it into something else like a list (or array) of data objects. As long as your list/array implements IEnumerable you should be able to just assign the list to the ItemsSource property of the aforementioned repeater control and it will perform its magic.
You don't even have to use a SQLCommand and DataTable object - you could even use Linq to SQL and bind the results straight to your repeater control.
This is just a high level overview of how you could do it, there are a couple of different ways. Once done, your code is going to be way cleaner and more maintainable than the classic ASP code.
Edit: your main issue is how to produce an ordered list, which is what the current code is doing with its nested loops supplying IDs for the detail items.
I would suggest you take a step back, and rethink the sql. In fact, throw the current sql away, it is incredibly inefficient with the tools you have today. It takes literally tenths of a second, and just one database call to return a flat table of data. Your first instinct may be "but i don't want to return too much data!" - relax, even returning several thousand data rows can be a sub 1 second operation if done correctly. You can also restrict the returned data by passing parameters in to the stored proc, or appending them to the dynamic sql statement that you construct (although it pains me hugely to mention dynamic sql, i think it is evil, but some people still use it - i would not recommend it unless it was your only option). To sum up what i am saying, how your data is returned from the database and how it looks on screen are two different things, don't let one guide the other. You can get the data from the database, then manipulate it before rendering it to the UI.
If you still want to show the data as an ordered list, then use a ListView, define a template for each data item, then you can use LINQ to group or filter the data you like (the data item template can contain whatever HTML or ASP.NET controls you like, and that template gets rendered for each data item in the list of data). Alternatively, you could use a GridView, and then use the grouping capability of the GridView to do the work for you - just specify which column(s) you want to group on, and the GridView takes care of the rendering.

Resources