unreliable information returned - c#

I'm writing an upgrade program for moving Access 2.0 .mdb files to Access 2003 .mdb. We are staying with the mdb file structure for a couple of reasons as this is code that is in several customers locations, and the mdb allows us to utilize existing code.
The main problem:
I go through JET to read in the tables from the file.mdb and read each table into a C# datatable. I then do several checks and duplicate the table in the 2003 mdb db. I use the DataTable.PrimaryKey function to gather the columns that are primary key columns, but I don't get reliable results.
Access 2.0 shows the PrimaryKey in several tables (single column) where DataTable does not, but not always.
I have verified that I do get the PrimaryKey(s) on some tables, just not all.
DataColumn[] dcPrimaryKeyCols = OrgTbl.PrimaryKey;
//Read the Ordinal so we can order the columns correctly
for (int m = 0; m < NumCols; m++)
{
ColumnOrder[m] = OrgTbl.Columns[m].Ordinal;
if (ColumnOrder[m] != m)
MessageBox.Show("In table " + nm+ "out of order ordinal on column: " + OrgTbl.Columns[m].ColumnName);
}
lblStatus.Text = "Creating Table";
pbTableProgress.Value = 0;
pbTableProgress.Maximum = NumCols;
for (int col = 0; col < NumCols;col++ )
{
pbTableProgress.Value = col;
Application.DoEvents();
sColNm=OrgTbl.Columns[col].ColumnName.Trim();
bPrimaryKey = false;
//determine if this column is part of a primary key group
for (int k = 0; k < dcPrimaryKeyCols.Length;k++ )
{
if (dcPrimaryKeyCols[k].ColumnName.Trim().Equals(sColNm))
{
bPrimaryKey = true;
break;
}
}
I have set a breakpoint in the bPrimaryKey = true line, and it gets there sometimes, but not on all the tables where a primarykey is defined.
One thing I noted, in Access Ver 2.0, the column information for the some of the primary keys show: required = no, unique = no. I don't know if this causes JET or the C# datatable to unmark a primarykey column or if other things are at work here. But the end results is that I am not able to correctly detect ALL primarykey columns.

Related

How to insert a datatable into an existing Database and overwrite duplicates?

I currently have a data table which adds new rows based on the Access table rows. In the data table, I change the value of certain columns and update them back to the database. I want to write a line of code that overwrites the data if the primary key already exists. I already looked into a query INSERT INTO table (id, name, age) VALUES(1, "A", 19) ON DUPLICATE KEY UPDATE name="A", age=19 but I can't find a way to implement this since i'm using a data adapter.
I have made the following code:
for (int i = 1; i < 19; i++)
{
Normen.Clear();
Normen.Add(-1);
for (int j = 9; j < 18; j++)
{
Normen.Add(Convert.ToInt32(NormDb.Rows[j].Field<double>(i)));
}
newRow[i] = Convert.ToInt32(GlobalMethods.LeftSegmentIndex(Normen, Convert.ToInt32(newRow[i + 18])));
}
schoolDb.Rows.Add(newRow);
Normen is in this case a list with integers i use to calculate test scores which are then inserted into the empty columns i fetched from the database table.
when this code runs, i have a datatable with rows and columns which are identical to the database columns. When this code is done, the other method is triggered to update the data into the datatable like this:
using (var dbcommand = new OleDbCommand(ZoekQuery, connection))
{
using (var SchoolAdapter = new OleDbDataAdapter(ZoekQuery, connection))
{
OleDbCommandBuilder cb = new OleDbCommandBuilder(SchoolAdapter);
cb.GetInsertCommand();
SchoolAdapter.FillSchema(schoolDb, SchemaType.Source);
SchoolAdapter.Fill(schoolDb);
Normeringen.Normeer(exportDb.Rows.Count, schoolDb, exportDb, NormDb, normcode);
SchoolAdapter.Update(schoolDb);
MessageBox.Show(Success);
}
}
But when the primary key already exists i want to overwrite the record because in this use case it is possible to grade a test with 2 different values. Is there any way i can implement this?

How to query table structures from an access database?

I want to get the structure of all the tables and odbc-Datasources in an Access database with C#. So I tried this code:
string text="";
var tables = GetApp().CurrentData.AllTables;
for (int i = 0; i < tables.Count; i++)
{
var currentTable = tables.Item(i);
text = text + currentTable.FullName + Environment.NewLine;
}
MessageBox.Show(text);
This returns all the availible tablenames. But how do I get the columnnamens and types of the tables?
I tried this:
var props = currentTable.Properties;
for (int j = 0; j < props.Count; j++)
{
var prop = props.Item(j);
text = text + Environment.NewLine + prop.Name;
}
but it didnt work (An exception was thrown when I accessed the properties).
I tried to use a oleDB connection + GetSchema to get the table structure. But with this method I only received the "native" (or local) tables inside of the access-db. But there are also some ODBC-Linked-Tables which I am also interested.
So how is it possible to get the TableNames, ColumnNames and Columntypes in an ms-access database file?
You need to use CurrentDb().TableDefs if you want to access table columns. The AllTables collection doesn't offer access to the table fields.
CurrentDb().TableDefs[0].Fields[0].Name should return the name of the first column of the first table, for example.

Column added to .net DataTable does not get added to database Table

I'm new to this site and I started some time ago to program an application.
Right now I'm stuck at a problem and I have no idea how to solve it.
My problem is: I want to register every user in a new column, because I have to save a great amount of data for each of them (up to 1000 rows). Now I add a new column to the already existing table. But the thing is, if I want to retrieve this data I get an error that says there is no column called like this.
programDataSet.User.Columns.Add(textBoxUser.Text, typeof(Int32));
for (int i = 0; i < 4 && i < alchemieDataSet.User.Count; i++)
{
programDataSet.User[i][textBoxUser.Text] = "1";
}
for (int i = 0; i < programDataSet.User.Count; i++)
{
alchemieDataSet.User[i][textBoxUser.Text] = "0";
}
this.Validate();
this.userBindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.programDataSet);
MessageBox.Show("Registration completed");
Does anyone have an idea what I made wrong?
I agree with everyone that there are big red flags with data architecture.
But to your specific question, DataSets and Adapters do not change table columns in a target database. They only change rows.
You have to update the columns separately.

Comparing different tables from different databases

I am using c#, asp.net
I have two different tables from two different databases.
Both Have one field in common that I am interested in say custid
I have assigned both to data tables but what I would like to do is this
Compare the two datatables (maybe with a dataview, which I have never used before)
to see what custid are missing from either table,
then i can insert or delete them from the first table , as I want the first table to have the same custid's as the second table.
Table 1 Table 2
1 1
2 - want to delete from table 1
3 3
4 - want to add to table 1
Any help would be appreciated.
As I didn't want to display the data just manipulate it
What I did in the end was
string [] servercustomers = new string [servercustomertable.lenght];
for (i = 0; i < servercustomertable.length; i++)
{
// run query to see if current record exists in localtable
// if it does update it
// if it doesnt create it
servercustomer[i] = servercustomertable.Rows[i]["Custid"];
}
// check through the localtable
for (i = 0; i < localcustomertable.length; i++)
{ bool recordexist = false;
// check through the array to see if the custid is there
for (j = 0; j < servercustomer.length; j++)
{
if (servercustomer[j] = localcustomertable.Rows[i]["custId"])
{
recordexists = true;
break;
}
if(!recordexists)
// delete the record from the local table
}
}
Thanks for all your help
Rachael

Update 1 column using bulkinsert C#

I have dataabase of 2.5 million records. One column in database is empty. Now i want to fill that column by inserting in Bulk, because a simple update query takes a lot of time. But the problem is that bulkinsert starts inserting record at the end, not from the start. Here is my code:
using (SqlBulkCopy s = new SqlBulkCopy(dbConnection))
{
for (int j = 0; j < rows.Length; j++)
{
DataRow dailyProductSalesRow = prodSalesData.NewRow();
string[] temp = ((string)rows[j]["Area"]).Split(new string[] { " ", "A","a" }, StringSplitOptions.None);
if (Int32.TryParse(temp[0], out number))
{
int num1 = Int32.Parse(temp[0]);
dailyProductSalesRow["Area1"] = 1;
}
else
{
dailyProductSalesRow["Area1"] = 0;
Console.WriteLine("Invalid "+temp[0]);
}
prodSalesData.Rows.Add(dailyProductSalesRow);
}
s.DestinationTableName = prodSalesData.TableName;
foreach (var column in prodSalesData.Columns)
{
s.ColumnMappings.Add(column.ToString(), column.ToString());
}
try
{
s.WriteToServer(prodSalesData);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
If you need to update, use an UPDATE stamenet
BULK INSERT is designed to help make inserting many records faster as INSERT can be very slow and difficult to use when trying to get a large amount of data into a database.
UPDATE is already the fastest way of updating records in a database. In your case I'd guess you want a statement a bit like this based on what your BULK INSERT is apparently trying to do.
UPDATE SalesData
SET Area1 = CONVERT(INT, SUBSTRING(Area, 0, CHARINDEX('A', Area)))
If you want to try and make it faster then try looking at Optimizing Bulk Import Performance. Some of the advice there (e.g. the recovery model used by the database) may also be applicable to UPDATE performance when updating many records.

Categories

Resources