The safe methods and convention standards of datasets, datatables, datarows - c#

What are the essential controls before getting a piece of data from a row of a table of a dataset in c#? In order to get rid of the errors while converting a nullable data into decimal, or getting a coloumn that may not be in the datasource any more?
What do I do to validate the existence of a column?
I check if the datarow is not DBNULL.Value before a convert operation to decimal.
I do check if the coloumn exists among the coloumns of the datarow.
What I do look for?
Are there any util class to manuplate the datasets, datatables to get row or an attribute's data? Or please tell me the possible check list over datasets, datatables, datarows to be always sure about no convertion error, no such an error linking with a dataset and its child objects.
Thank you!

If you want to check if a column exists in the datatable you can simply do this:
YourDataTable.Columns.Contains("column")
If you want to check if the value of a target row is null then I would do like this:
if(!Convert.IsDBNull(YourDataTable.Rows[0]["column"]))
{
//Something
}
If you get a dataset back you proboly also want to check if there is a DataTable
If(YourDataSet.Tables.Count>0)
{
//something
}
Depending on how may rows you are expecting. If you are expecting one row the you can do this:
if(YourDataTable.Rows.Count>0)
{
//something
}

Related

WebGrid MVC refer to previous row values

At the time of populating the table, is it possible to refer to a column in a previous row?
So something like this: Refer to an other columns value in a MVC3 Razor WebGrid Except I want to refer to the same column but from a previous role.
For example, this is the column I'd like to know all values for:
//check if statement before creating it
foreach(Column("Prop") c in allRowsCollection) {
if(c.Value = "something") { //check if there is already a row with a specific value for this column
grid.Column("Prop", "example1"),
}
else {
grid.Column("Prop", "example2"),
}
}
So every time I add a new row, I'd like to compare it with the previous one.
Is this possible? If not, is there some workaround?
If you bind to against a datasource you can check the datasource and not the grid.
I would however sort this out during my sql call and omit any front end checking.
Chances are it'll be faster too because you're not moving as much data over the wire.

How do I save info from an unbound datagridview to SQL database

I have been trying for hours to get the info in my datagridview to save to the datatable. The datagridview is populated from a combobox where selections are made. What I cant figure out is how to convert the qty_Ordered to int. I believe it will work once I have that.
Also, is it possible to use the column names of the datagridview rather than Cells[]?
foreach (DataGridViewRow row in purchase_Order_ItemsDataGridView.Rows)
{
if (!row.IsNewRow)
{
SQL = #"INSERT INTO Purchase_Order_Items (Purchase_Order_ID, Part_Number, Qty_Ordered, Work_Order_Number)
VALUES(#purchase_Order_Id, #part_Number, #qty_Ordered, #work_Order_Number)";
sqlCommand = new SqlCommand(SQL, DataAccessClass.sql_Connection);
sqlCommand.Parameters.AddWithValue("#purchase_Order_ID", purchase_Order_Id);
sqlCommand.Parameters.AddWithValue("#part_Number", row.Cells[1].Value);
sqlCommand.Parameters.AddWithValue("#qty_Ordered", row.Cells[2].Value);
sqlCommand.Parameters.AddWithValue("#work_Order_Number", row.Cells[3].Value);
sqlCommand.ExecuteNonQuery();
}
}
Have you tried this? Admittedly a stopgap solution but it does convert it to int.
sqlCommand.Parameters.AddWithValue("#qty_Ordered", int.parse(row.Cells[2].Value.ToString()));
edit: This link might help you more -
Get Numeric Value from DataGridViewCell?
It deals with ways to convert the cell with a bit more robustness than the above solution, would would fail dramatically when your value is null.
edit 2: Looks like the above solution isn't robust enough. The below code is more robust.
int qtyordered;
if (!int.TryParse(row.Cells[2].Value.ToString(), out qtyordered)
qtyordered = 0;
sqlCommand.Parameters.AddWithValue("#qty_Ordered", qtyordered);
Loathing's answer would work the best since it'd work transparently with your current code, however it's a bit tricky. You need to expose the datatable's column so that you can modify the type. And you need to do that when / after the column has been created and before you begin adding data.
purchase_Order_ItemsDataGridView.Columns[2].ValueType = typeof(int);
You need to put this somewhere early on, before you begin populating the table but after you created the columns.

Reading column from local database c#

This is a really simple question I am sure, so please bear with me. I have created a local database in visual studio 2010. I have created a table with columns (c1,c2). I have also created a dataset using VS's wizard. This includes a ListTableAdapter. I am able to fill the database with values, but I am unable to get all of the rows in c2. Could anyone provide an example of getting a collection of rows from a specified column in c#? Please let me know if you need clarifying details.
Columns don't have rows. You iterate through rows and choose the field.
e.g. something like
foreach(DataRow row in MyDataset.Table["TableName"].Rows)
{
yield return row["FieldName"];
}
What type do you want and how do you want to deal with nulls will be a consideration.
Bear in mind that ColumnName in the table being fieldName in the datatable is a default.
Equally columns have native types, but a field in a DataRow is an object, which if null in the database will be set to DBNull.Value.

How to make all columns allow null before adding a new row?

How to make all columns allow null before adding a new row to the datatable .
dt.Rows.Add(dt.NewRow());
This line throws an exception
Column XXX does not allow nulls
How to fix this problem.
You don't add the row until it's filled and ready to be saved.
DataRow row = dt.NewRow();
...fill row with values...
dt.Rows.Add(row);
Usually the database designer specifies that a column can't be null for a reason. For example, it might be a primary key or a foreign key, or is otherwise mandatory information.
If you are sure that it is OK to provide no data for this column for this particular record, try passing an empty string.
It is usually better to initialize the whole row in memory before sending it to the database (instead of filling it field-by-field when it is already there).
However, if you absolutely must do that, and if your DBMS supports it, you can declare your NOT NULL constraints as deferred, so they are not checked until the transaction commits. Here is an Oracle example.
It's rarely good solution. Start from redesigning your database.
Consider removing NOT NULL constraints from all not necessary fields.
Also if any fields is obligatory, but you still do not want to fill it during row creation, set default value either in database or middle layer (ORM or whatever)
edit:
however, in this case it looks like you're just trying to pass an empty row to db, before initializing it with data. That will never work ;-)

How to create LookUp fields in DataGridView?

In my DataGridView I'am displaying a buch of columns from one table. In this table I have a column which points to item in another table. As you may already guessed, I want to display in the grid in one column some text value from the second table instead of and ItemID.
I could not find a right example on the net how to do this.
Lets assume that I have two tables in databes:
Table Users:
UserID UserName UserWorkplaceID
1 Martin 1
2 John 1
3 Susannah 2
4 Jack 3
Table Workplaces:
WorkplaceID WorkplaceName
1 "Factory"
2 "Grocery"
3 "Airport"
I have one untyped dataset dsUsers, one binding source bsUsers, and two DataAdapters for filling dataset (daUsers, daWorkplaces).
Code which I am performing:
daUsers.Fill(dsUsers);
daWorkplaces.Fill(dsUsers);
bsUsers.DataSource = dsUsers.Tables[0];
dgvUsers.DataSource = bsUsers;
At this point I see in my dgvUsers three columns, UserID, UserName and UserWorkplaceID. However, instead of UserWorkplaceID and values 1,2,3 I would like to see "Factory", "Grocery" and so on...
So I've added another column to dgvUsers called "WorkplaceName" and in my code I am trying to bind it to the newly created relation:
dsUsers.Relations.Add("UsersWorkplaces", dsUsers.Tables[1].Columns["WorkplaceID"], dsUsers.Tables[0].Columns["UserWorkplaceID"]);
WorkplaceName.DataPropertyName = "UsersWorkplaces.WorkplaceName";
Unfortunately that doesn't work. Relation is created without errors but fields in this column are empty after running the program.
What I am doing wrong?
I would like to also ask about an example with LookUp combobox in DataGridView which allow me to change the UserWorkplaceID but instead of numeric value it will show a tex value which is under WorkplaceName.
Thanks for your time.
In my opinion, the best decision would be to use the DataGridViewComboBoxColumn column type. If you do it, you should create a data adapter with lookup data beforehand and then set DataSource, DataPropertyName, DisplayMember, and ValueMember properties of the DataGridViewComboBoxColumn. You could also set the DisplayStyle property to Nothing to make the column look like a common data column. That's it.
I don't know if you can do exactly what you want, which seems to be binding the DataGridView to two different DataTable instances simulataneously. I don't think the DataGridView class supports that -- or if it does it's a ninja-style move I haven't seen.
Per MSDN, your best bet is probably using the CellFormatting event on the DataGridView and check for when the cell being formatted is in the lookup column, then you could substitute your value from the other table. Use an unbound column for the WorkplaceName column, hide the UserWorkplaceID column and then implement the CellFormatting event handle to look up the value in the row, e.g.:
private void dgv_CellFormatting(object sender,
DataGridViewCellFormattingEventArgs e)
{
if (dgv.Columns[e.ColumnIndex].Name.Equals("WorkplaceName")
{
// Use helper method to get the string from lookup table
e.Value = GetWorkplaceNameLookupValue(
dataGridViewScanDetails.Rows[e.RowIndex].Cells["UserWorkplaceID"].Value);
}
}
If you've got a lot of rows visible, this might impact performance but is probably a decent way to get it working.
If this doesn't appeal to you, maybe use the DataTable.Merge() method to merge your lookup table into your main table. A quick glance at one of my ADO.NET books suggests this should work, although I have not tried it. But I'm not sure if this is too close to the idea suggested previously which you shot down.
As for your second question about the lookup combobox, you should really post it in a separate question so it gets proper attention.
You could make SQL do the job instead. Use a join to return a table with Workplace names instead of IDs, output that table into a dataset and use it instead.
eg.
SELECT A.UserID, A.UserName, B.WorkplaceID
FROM Users A
JOIN Workplaces B ON A.UserWorkplaceID = B.WorkplaceID
Then use its output to fill dsUsers.

Categories