SqlDataSource_OnSelected: Get data (DataTable) without re-executing the query - c#

I have a SqlDataSource bound to a GridView with an SQL that takes about 10 seconds to retreive the data.
Also there is a UserControl called "PageSizeControl" which hooks the selected-event of the GridView's SqlDataSource. In this event, I need the DataTable to prepare some settings of the PageSizeControl.
Currently, I'm doing this with following code:
protected void ds_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
SqlDataSourceView dsv = (sender as SqlDataSourceView);
dsv.Selected -= ds_Selected;
DataTable dt = (dsv.Select(DataSourceSelectArguments.Empty) as DataView).Table;
int iRowCount = dt.Rows.Count;
// some gui-adaption like visibility, text, ...
}
In older versions we used e.AffectedRows. But the value stored in e.AffectedRows is not correct when a Filter is applied to the DataSource. And we have use-cases where we don't only need the row count but the whole DataTable.
The problem is, that the .Select() re-executes the Db-Query and this takes another 10s to finish.
I also tried to turn caching on the SqlDataSource on:
EnableCaching="true" CacheDuration="Infinite"
But this wasn't helpful in two reasons:
1. The OnSelected event is not fired when cached data get accessed
2. If the OnSelected event get's fired (because data wasn't yet cached), the .Select() is still executing uncached and takes 10s.
Does anybody have clues how I can get the data without a time-consumpting re-execution of the query? Best would be in the OnSelected, but I'm open for another suggestions.

I got a workaround running that fits my requirements. I use the event GridView.OnRowDataBound and get the DataItem of the first GridRow, which contains the DataTable.
private DataTable oData = null;
protected void gv_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (oData == null && e.Row.DataItem != null)
{
oData = (e.Row.DataItem as DataRowView).Row.Table;
}
}
This solution works, but it looks quite dirty and it requires a GridView (which in my case is no problem). I would be grateful for a more clean solution.
UPDATE
After a longer research with IlSpy I got to the conclusion that it is not possible to get the data in the OnSelected event. Even not if caching is enabled, since cache is written after OnSelected.
So the easiest way is to turn cache on and call the SqlDataSource.Select(...) function where you need the data.
Another way is to get the data by yourself with SqlDataSource.Select(...) and then bind the table it to the controls. But this has some disadvantages. For example: sorting and paging on GridView doesn't work out of the box when bound to a dataset/datatable.
And yet another way is to extract the data from the control which selected it. See above for an example for GridView.

Related

RowLoaded event - can't modify cell content

During development with Devexpress, we've encountered the use of a InstantFeedbackSource. Using the Row_Loaded, we would like to adjust values of certain rows. Yet the CellContent isn't changed.
Testsolution:
GetQueryable-Method of my datasource:
private void linqInstantFeedbackSource1_GetQueryable_1(object sender, GetQueryableEventArgs e)
{
e.QueryableSource = _testObjects.AsQueryable();
gridView2.RefreshData();
gridControl2.RefreshDataSource();
}
My Row-loaded event
private void gridView2_RowLoaded(object sender, DevExpress.XtraGrid.Views.Base.RowEventArgs e)
gridView2.SetRowCellValue(e.RowHandle, gridView2.Columns["RandomGuid4"], "lalalala");
}
Information:
gridView2.Columns["RandomGuid4"] is not null and refers to the correct-column.
e.RowHandle Refers to the correct Linenumber
Goal:
I want to achieve the following behavior:
At runtime i want to fill the gird with records. When adding the rows i want to check the row for certain values. When a certain value occurs then several another cells should be filled with combobox, hyperlinks,...
The advised way by devexpress is the event CustomCellEdit. But that event is highly unreliable. We're experiencing issues (exceptions from within the control). I've submitted several tickets so far but no response. So we're searching an alternative.
Could someone point out what i'm exactly missing/doing wrong here?
Thank you for your time.
Note: I've tried the use of RefreshData in my RowLoaded-Event but it doesn't appear to be working.

Using stored proc in LinqDataSource to populate GridView

As in the title I need to use stored proc to feed LinqDataSource to populate result in GridView. I got this concept to work in SqlDataSource but then I had Authentication issues (I'm running the app on tablets that can't provide Integrated Authentication that SQL Server requires - and I do not want to change SQL configuration). Linq works perfectly for me except when I try to use Calendar control to feed WHERE parameter. The stored proc worked much better and I could receive correct sets but now I have problems populating that to GridView.
Here is the code:
protected void myLinqDataSource_Selecting(object sender, LinqDataSourceSelectEventArgs e)
{
DataContext myContext = new DataContext();
e.Result = myContext.myTable(myCalendar.SelectedDate);
}
protected void myCalendar_SelectionChanged(object sender, EventArgs e)
{
myLinqDataSource.DataBind();
myGridView.DataBind();
}
In this configuration the pool times out. If I move binding to event handler, there would be nothing supplied to grid view. Maybe you know a better way to use stored procs with LinqDataSources?
So since there was no answers here is one that I arrived at. LinqDataSource is great but pretty hard to configure declaratively. I used LDS dynamically to feed set into a List<>() and bound GridView to it. Worked perfectly!

Accessing cells in a gridview

Last week I started attempting to use Winforms to automate some reports. I am not enjoying the transition (as simple as it may be to some of you)!
I am currently displaying data from a SQL view that I created using Oracle SQL Developer. I accecssed the data by using the DataGridView Tasks to select the table and display it (it seemed like the most straightforward method).
All of the data displays fine. However, I would now like to access the cells in the table. I want to be able to alter the colours of the cells based upon their values and to pull out some of the data if needs be.
To access the data and highlight the rows I was hoping to do something like this
protected void MyGridView_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
int theValue = Convert.ToInt32(e.Row.Cells[0].Text);
if (theValue>0)
e.Row.Cells[0].BackColor = System.Drawing.Color.Red
}
}
It doesn't work because the event is not firing. I think I am supposed to bind the data to my gridview but I have loaded all of the data through the designer. Is this the problem? I have no idea how to code it myself, I tried before but it threw a wobbly.
Furthermore, when I try to change the SQL query for the database through the designer it does not work. I think I am going to lose my mind at this rate!
You need to use the CellFormatting Event on the DataGridView like so
private void MyGridView_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if ((int)MyGridView.Rows[e.RowIndex].Cells[0].Value > 30)
{
e.CellStyle.BackColor = System.Drawing.Color.Red;
e.CellStyle.ForeColor = System.Drawing.Color.White;
}
}

Accessing ItemTemplate from codebehind

I have a GView and I am populating rows from code behind. However, in the RowUpdating event I want to access the changes done by the user and store that change into a string. Here is my code:
protected void gvShowComm_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
System.Web.UI.WebControls.TextBox myBox = gvShowComm.Rows[e.RowIndex].FindControl("PlanName") as System.Web.UI.WebControls.TextBox;
string s = myBox.Text;
gvShowComm.DataBind();
}
string s is still showing me the OLD text which is populated before. I want to store new string which user entered. How do I do that?
make sure you repopulate rows and call DataBind at least on PageLoad, preferably on OnIniti without doing that, you always get values from viewstate (if you didnt disable it). at a last resort, you can investigate Request.Form and find if you recieved new value properly
Can't you use e.NewValues[] . The result that you are getting is probably e.OldValues[]

C# DataGrid automatically write values to DB

I have a datagrid view which shows table data from a database
Environment:
- C# 4.0
- SQL Server 2005
- Visual studio 2010
What i want is: On a row to row basis automatically save changes. So when I edit the first row and then leave the row. It should save the changes to the database.
I've used this code:
In the From1 Load:
dataSet1.TblObject.RowChanged += rowUpdate;
The eventhandler:
private void rowUpdate(object sender, DataRowChangeEventArgs e)
{
DataRow dr = e.Row;
if (dr.RowState == DataRowState.Modified)
{
tblObjectTableAdapter.Update(dr);
}
}
When I've edited a row in the grid, tblObjectTableAdapter.Update(dr); is called the data is stored to the table. Which is good. But the event keeps on triggering as if it's called recursively. So the tblObjectTableAdapter.Update(dr); is causing a dataSet1.TblObject.RowChanged event. But I can't differentiate between the both of them. I'm guessing I'm using the wrong event to store my values but I can't find any event that sounds logical to me. What am I doing wrong?
I've made a dataset xsd:
I've picked the dataset as datasource in this gridview:
Ok, I read your post a couple of times now, while I can't help u directly with your problem. I'll try anyway, What u want is that when i make a change, it doesn't update itself immediatly, but saves the information in a list and when u press a button save the updates?
Then You should make a List of Datarows, and each time a row is changed add that item to the list, this way the updates aren't made directly, but only when u press the button. (This is also way better for performance sake.)
So instead of the code
DataRow dr = e.Row;
if (dr.RowState == DataRowState.Modified)
{
tblObjectTableAdapter.Update(dr);
}
U should make
DataRow dr = e.Row;
if (dr.RowState == DataRowState.Modified)
{
DatarowLst.Add(dr);
}
ButtonSave_Click(object sender, eventargs e)
{
foreach (DataRow d in DatarowLst)
{
tblObjectTableAdapter.Update(d);
}
}
EDIT:
Ok sorry for misunderstanding u. I now understand your problem and looked into the issue.
I found some interesting information on Data adapters and tables. It seems the Adapter does a row to row check in order to obtain information about the changes made.(i.e does it need a update or delete command?) Thereby, My GUESS is that this triggers a update to occur and therefore call your event again, and running the method recursivly.
Info found at the REMARK piece on: This site from msdn
They give a link to this site for more information. Maybe you'll find your answer there.
As to a solution for your problem it seems u can leave your event out and just call the update command. Im NOT sure about this cause I dont have time to check on this and I have little experience on this subject.
Well, hope this helps u a bit further..

Categories

Resources