Reading column from local database c# - 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.

Related

The safe methods and convention standards of datasets, datatables, datarows

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
}

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 ;-)

OleDbDataAdapter datatype mismatch using Jet

I'm using an OleDbDataAdapter (Microsoft.ACE.OLEDB.12.0 to be precise) to retrieve data from an Excel workbook. For one table I'm using a typed dataset but for another table I can't do that since the number of columns is unknown (the Excel template may generate extra columns).
The problem was that if someone enters too many numeric values in a column, "JET" seems to assume it's a numeric column and the textual values are not loaded anymore. I know you can change the template and set the specific data type for that column but the template is already widely spread so I'd rather resolve it during import.
Now what I tried was first counting the number of used columns and preparing a new DataTable with a defined Columns collection and setting their DataType property to typeof(string). Sadly JET doesn't seem to be looking at this and still chooses it's own way. I'm guessing that even if I could use a strongly typed dataset here, it wouldn't help either...
Does anyone know how to tell JET how to import the data so I don't have to face the burden of delivering a new template version?
Please *PLEASE*: don't come with an Excel automation solution...
If you have access to the registry set TypeGuessRows=0 and/or ImportMixedTypes=Text. See here for more info INITIALIZATION SETTINGS

c# DataSet with 2 tables, how to delete a row from one it will delete a row from the other?

I use Visual Studio 2010
I have a DataSet with 2 tables
one (MainList) has type, name, path, parameter
the other (UpadteList) has path, hash, date
I added files to this list and it work with out problem, now I have the following
when I add file type "update"
it will be "Update","My Program", "PATH-TO-/my.setup.exe","/minimized"
if it was type "Update"
the following data goes to (UpdateList)
"PATH-TO-/my.setup.exe","asdfwefwfgg3r34t34t34t","2010-09-01"
I want when a row in the (MainList) deleted and a row with the same path in (UpdateList) exsist it will deleted too
should I use loop or (I saw) in dataSet properties use Relations
what is the best approach ?
with loops I got into some ugly bugs that delete everything in the Mainlist!
note: I use XML to store data (the data is not big)
IMO, you have two choices
Use DataTable constraints such as ForeignKeyConstraint with DeleteRule=Cascade settings.
Use RowDeleted/RowDeleting event on MainList data-table to look up and delete the corresponding row in other table.
I think that code is arguably the wrong place to deal with data consistency. I'd do it in the database, either in a stored procedure or, if you're using SQL Server, possibly with cascading deletes.

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