i have a dataset which contains three tables dt1, dt2, and dt3 (in the sequence), now i am maintaining the viewstate for every table, to retain the table across postback, (i.e i have latest DataTable inside viewstate), now the problem is i want to apply ViewState of dt3 to the respective table in DataSet, i.e dt3, i am doing below:
dataSet.Tables[(it will be dynamically fetched, say for here its) 0] = ViewState["DataTable" + (it will be dynamically fetched, say for here its) 0]
but here i am getting error saying dataSet.Tables[] is read-only.
can any one help how shall i go about at. Let me know if anyone needs more information about my question.
You should use
DataSet ds = new DataSet();
ds.Tables.Add(YourDataTable);
OR
ds.Tables.AddRange(YourDataTableArray);
To update an existing table in ds from ViewState you can try two approaches.
Remove Table from DataSet by using DataSet.Tables.Remove("Table"); method, Note that you should not rely on index approach to fetch Tables from DataSet instead you should provide your Tables a unique name so that you can fetch and remove them when you want to.
You can use loop approach to fetch rows from your ViewState DataTable and then insert them into DataSet's Table one by one, Something like this.
ds.Tables[0].Rows.Clear();
DataTable dtFromViewState = ViewState["dt"] as DataTable;
foreach (DataRow row in dtFromViewState.Rows)
ds.Tables[0].Rows.Add(row.ItemArray);
Related
In my ASP.NET web app I have a DataTable filled with data to insert into tblChildren.
The DataTable is passed to a stored procedure.
In the SP I need to read each row (e.i Loop through the DataTable), change a couple of columns in it (with accordance to the relevant data in tblParents) and only then insert the row into tblChildren.
SqlBulkCopy wouldn't do and I don't think TVP will do either (not sure... not too familiar with it yet).
Of course I can iterate through the DataTable rows in the app and send each one separately to the SP, but that would mean hundreds of round trips to the SqlServer.
I came across two possibilities that might achieve that : (1) Temp table
(2) Cursor.
The first is quite messy and the second, as I understand it, is NOT recommended)
Any guidance would be much appreciated.
EDIT :
I tried the approach of user-defined Table Type.
That works because I populate the Table Type (TT_Children) with values in the TT_Child_Family_Id column.
In real life, though, I will not know these values and I would need to loop thru #my_TT_Children and for each row get the value from tblFamilies, something like this :
SELECT Family_Id FROM tblFamilies WHERE Family_Name = TT_Child_Last_Name
(assuming there is always an equivalent for TT_Child_Last_Name in tblFamilies.Family_Name)
So my question is - how to loop through the table-type and for each row look up a value in a different table?
EDIT 2 (the solution) :
As in Amir's perfect answer, the stored procedure should look like this :
ALTER PROCEDURE [dbo].[usp_Z_Insert_Children]
#my_TT_Children TT_Children READONLY
AS
BEGIN
INSERT INTO tblChildren(Child_FirstName,
Child_LastName,
Child_Family_ID)
SELECT Cld.tt_child_FirstName,
Cld.tt_child_LastNAme,
Fml.Family_Id FROM #my_TT_Children Cld
INNER JOIN tblFamilies fml
ON Cld.TT_Child_LastName = Fml.Family_Name
END
Notes by Amir : column Family_Name in tblFamily must be unique and preferably indexed.
(Also I noticed that in case TT_Child_LastName does not have a match in tblFamilies, the row will not be inserted and I'll never know about it. That means that I have to check somehow if all rows were successfully processed).
You can join tblFamilies into the insert in the procedure and take the value from there. Much more efficient than looping through.
Or create a cursor and do one child at a time.
1) Make sure there is only one occurance of FamilyName in tblFamilies.
2) Make sure that if tblFamilies is a large table, then the FamilyName column is indexed.
INSERT INTO tblChildren(Child_FirstName, Child_LastName, Child_Family_ID)
SELECT Cld.tt_child_FirstName,
Cld.tt_child_LastNAme,
Fml.FamilyID
FROM #my_TT_Children Cld
INNER JOIN tblFamilies fml on Cld.TT_Child_LastName = Fml.FamilyName
But be aware that if tblFamilies has more than one entry per Family_Name, then this will duplicate the data. In this case you will need to add more restrictions in the where.
I'm using a huge datatable for a survey analysis. Instead of calling SQL server frequently am using row filtering on this datatable using DataView.
But the problem is once I filter the DataTable by
dv= dt.defaultview
dv.rowfilter="id=10"
that works fine. Dv having a filtered rows
But when we assign the same dt to another view, the Main datatables Default view being changed based on the filteration done for DV which is ID=10
So in the immediate window I checked this
dt.defaultview.totable().rows.count
and its 20 (WHich was because of the filteration done for DV)
but
dt.rows.count
is 1500 which is the correct count.
But my question is how this happened since I didnt touched the Datatable and I assigned the filter for DV only. Even then how the defaultview of the datatable changed?
"Even then how the defaultview of the datatable changed?" Isn't that obvious if you look at the first two lines of code you have posted?
dv = dt.DefaultView
dv.rowfilter = "id=10"
If you want to remove that filter on the DefaultView you have to assign empty string or Nothing:
dt.DefaultView.RowFilter = ""
How would you write the code to read the data from a query and display each row in a separate label if you don't know how many rows the query result may contain? If you try to read one too many rows with the DataReader, it throws an excetion when you try to read the column data on the row that doesn't exist. I'm not sure how to code this.
If dr.HasRows Then
dr.Read()
LN2.Text = dr.Item("linenum").ToString
Else
LN2.visible = False
End If
This example shows how I am loading the second row with the DataReader. This works if there are two rows of data, but if there is only one row of data, it throws an exception. I have a maximum of 12 rows of data but, but my actual query results may contain anywhere between 1 and 12 rows of data.
The Read method returns a boolean indicating whether or not the read of the next row was successful. Therefore, you could change your code to something like this:
If dr.Read() Then
LN2.Text = dr.Item("linenum").ToString
Else
LN2.visible = False
End If
However, usually, in such cases, displaying varying numbers of rows of data in a fixed number of labels isn't the best approach. For instance, if you used a single ListBox control instead, all your loading code could be simplified to the following:
While dr.Read()
ListBox1.Items.Add(dr.Item("linenum").ToString())
End While
If you need to show multiple columns of data for each row, I would recommend using either a ListView control (with the View property set to Details) or a DataGridView control.
I have a spreadsheet in my local machine with columns(employee number and salary). I need to update employee table with this value. Mismatched rows has to be tabled in browser.
Using file upload control in visual studio .net I'm uploading excel sheet. When clicking on the button I need unmatched rows.
I think we can achieve this by using datasets to bring database values and compare with sheet, but what is the best way to compare?
Thanks
This is how we do it:
First, you should have atleast a 'comparison column' in each of your datasets (ie. Excel Sheet and Database table).
You will create 2 objects to hold the data for the excel sheet and the table records.
You will then populate them.
Next is where you will have a little magic. You will have to make a choice of which of the two is you primary dataset.
What next? .... loop through items.
Pseudo:
DataSet ds1 = .....;
DataSet ds2 = .....;
foreach record(r) in ds1 Table
foreach record(s) in ds2 Table
if record r = record s
store this as matched record and break
else
store this as mismached record (may need some more logic here)
endloop
endloop
Unfortunately I do not have a copy/paste function/method to do this but can provide guidance.
Hope this gives you a starting point.
i have a GridView bound to a DataView.
Some columns in the DataView's table are foreignkeys to related tables(f.e. Customer). I want to enable sorting for these columns too, but all i can do is sorting the foreignkey(fiCustomer) and not the CustomerName.
I have tried this without success(" Cannot find column ERP_Customer.CustomerName "):
<asp:TemplateField HeaderText="Customer" SortExpression="ERP_Customer.CustomerName" >
A tried also the DataViewManager, but i've a problem to detect the table to sort:
Dim daCharge As New ERPModel.dsERPTableAdapters.ERP_ChargeTableAdapter
daCharge.Fill(dsERP.ERP_Charge)
Dim viewManager As New DataViewManager(Me.dsERP)
viewManager.DataViewSettings(dsERP.ERP_Charge).RowFilter = filter
viewManager.DataViewSettings(dsERP.ERP_Charge).Sort = sort 'sort is the GridView's SortExpression
Me.GrdCharge.DataSource = viewManager.CreateDataView(dsERP.ERP_Charge)
I have to apply the sort on a distinct table of the DataViewManager, but this table would differ on the related tables.
I have bound the TemplateColumns in Codebehind in RowDataBound-Event f.e.:
Dim LblCustomer As Label = DirectCast(e.Row.FindControl("LblCustomer"), Label)
LblCustomer.Text = drCharge.ERP_CustomerRow.CustomerName 'drCharge inherits DataRow
What is the recommended way to sort a GridView on columns related to other tables? I could build a custom datatable with the customername instead of the foreignkey and bind this column to the TemplateField. But then my huge dataset in the model makes no sense anymore.
EDIT:
It seems that my question was not clear or too special.
Perhaps i can rephrase it in a more general term.
I have a model with a Dataset. I'm binding one Datatable(ERP_Charge) from it to my GridView(actually i take a Dataview from that Table). In this Datatable are columns that are related to other Datatables in the Dataset(relations are defined). When i want to make the grid sortable its no problem on the columns that belong to ERP_Charge. But the columns with foreign keys to other table could not be sorted because the Gridview shows f.e. not the CustomerID but the Customername. I get the Customername in RowDataBound.
Normally i would join the tables and add a Datacolumn for the Customername. Then i set this "virtual" Datatable as Datasource from the Gridview and i'm able to sort it. But i didnt want to create the datatables in the Page on the fly(it belongs into the model). Do i have to define it in the dataset-Designer? I thought it would be sufficient to define the relationships in the dataset.
UPDATE: i had solved my sorting problems as below.
Regards
UPDATE: i had solved my sorting problems in the following way: I changed my DataSet in the model and joined the related table to the Main-Table(ERP_Charge). I added the columns to the Datatable(f.e. CustomerName) that i want to sort. But i did that without saving it in the configuration wizard of the DataAdapter, because that would delete all Update-,Delete- and InsertCommands. Hence i changed only the SelectCommand with the one that was generated from the Wizard. Therefore i kept the benefit of my Datamodel with the ability to sort for columns of related tables. Maybe queries are a little slower now because of the joins but it works for me.