InvalidOperationException while trying bulkInsert the datatable into SQL Server - c#

I got data from text file into datatable and now when I am trying to insert that data into a SQL Server 2008 database, I get the following error:
InvalidOperationException: String or binary data would be truncated
I cannot get the source of error ie which record is throwing this error.
The code is as below
for (int i = 0; i < dt.Columns.Count; i++)
{
if (i == 159)
{
}
bulkCopy.ColumnMappings.Add(dt.Columns[i].ColumnName,DestTable.Columns[i].ColumnName);
}
bulkCopy.BulkCopyTimeout = 600;
bulkCopy.DestinationTableName = "dbo.TxtFileInfo";
bulkCopy.WriteToServer(dt);
I have the datatable in the dt variable. And matched columns for both datatable created from text file and also the empty table created in database to add the values to it.
I have copied all records from text file into datatable using below code.
while (reader.Read())
{
int count1 = reader.FieldCount;
for (int i = 0; i < count1; i++)
{
string value = reader[i].ToString();
list.Add(value);
}
dt.Rows.Add(list.ToArray());
list.Clear();
}
I have got proper records from the text file. Also the number of columns are equal. My database table TextToTable has all columns of datatype nvarchar(50) and I am fetching each record as string from text file. But during bulk insert the error shown is
Cannot convert string to nvarchar(50)

Seems you are trying to insert data which has less length in DB (for example: you have data length 20 but in DB accept only 10 )
To check data which is coming from text file. Have if condition to check length of data in your code and have break point to troubleshoot.
If yes then increase the length of column in DB.
alter tablename
alter column columnname varchar(xxx)

Related

How to add a column and values in to existing Data column from a string array

I have to add a data column in to the existing data table.
I need to add one more column and data to that table from a .txt file in to 0th column and from second column I need to keep the DB data.
I am not using any grid view and stream reader to my app. I need to use File.ReadAllLines();
My .txt file is like:
ClaimID
val1
val3
val5
I tried something and the data table is not coming properly. Data table coming like showing in the picture below (data is starting from last row of first column and skipped first rows):
What I have tried is:
if (tableName == "TestData")
{
var pathC = #"H:\claimdetails\claims\Claims.txt";
string[] result = File.ReadAllLines(pathC);
DataColumn Col = table.Columns.Add("Claim_ID", typeof(String));
Col.SetOrdinal(0); // set column to first position
DataRow row;
for (int i = 0; i < result.Length; i++)
{
row = table.NewRow();
row["Claim_ID"] = result[i];
table.Rows.Add(row);
}
}
adapter.Fill(table);
How can I get a proper data table?
Instead of adding rows to the data table, you can try,
table.Rows[i].[0] = result[i]

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?

SqlBulkCopy string NULL CSV

I'm trying to mass-insert a CSV file into a SQL Server database.
The process is .CSV files DataTable for SqlBulkCopy SQL Server.
In the file I have several NULL that this code returns as text, and should not be text:
var linea = line.Split(delimiter);
row = dt.NewRow();
for (j = 0; j < linea.Length; j++)
{
if (linea[j].ToString().ToLower() == "null")
{
row[j] = DBNull.Value;
}
}
dt.Rows.Add(row);
It's pretty vague on what's your problem is, but I think I know you want the data to be stored as datatype NULL instead of a string "NULL" in the DB.
From what I know about SQLBulkCopy into datatable, you can't manipulate the data to store NULL in database table. To deal with this, I used two work-around:
Remove the "NULL" inside the CSV before uploading. If the CSV comes from your users, advise them not to use "NULL" for cell that is suppose to be blank/empty. Just leave the cell blank. This is the most direct way, because the datatable will somehow store NULL into database table when the cell is blank.
Pretty sluggish way, replace all "NULL" value in datatable to blank ("") and store into database table. When SQLBulkCopy inserted all data, run an update statement to update all blank column to NULL.

Autodetecting Oracle data types

I'm trying to fetch data from multiple tables from an Oracle db and insert it into a sql db. The problem that I am running into is that I am fetching almost 50 columns of data all of different datatypes. I then proceed to insert these individual column values into a SQL statement which then inserts the data into the sql db. So the algo looks something like this:
Fetch row data{
create a variable for each individual column value ( int value = reader.getInt32(0); )
add a sqlparameter for it (command.Parameters.Add(new SqlParameter("value", value)); )
once all the 50 or so variables have been created make a sql statement
Insert into asdf values (value,........)
}
Doing it this way for a table with <10 columns seems ok but when it exceeds that length this process seems tedious and extraneous. I was wondering if there was a simpler way of doing this like fetch row data and automatically determine column data type and automatically create a varialbe and automatically insert into sql statement. I would appreciate it if anyone could direct me to the right way of doing this.
The data reader has a neutral GetValue method returning an object and the SqlCommand has an AddWithValue method that does not require to specify a parameter type.
for (int i = 0; i < reader.VisibleFieldCount; i++) {
object value = reader.GetValue(i);
command.Parameters.AddWithValue("#" + i, value);
}
You could also create the SQL command automatically
var columns = new StringBuilder();
var values = new StringBuilder();
for (int i = 0; i < reader.VisibleFieldCount; i++) {
values.Append("#").Append(i).Append(", ");
columns.Append("[").Append(reader.GetName(i)).Append("], ");
}
values.Length -= 2; // Remove last ", "
columns.Length -= 2;
string insert = String.Format("INSERT INTO myTable ({0}) VALUES ({1})",
columns.ToString(), values.ToString());

sqlite insert or replace datagridview C#

Regarding the Sqlite insert or replace command.
I am doing the insert if does not exist.
The inserted/updated values come from the datagridview bound to a datatable.
The datatable has a TID column which is the primary key. It also has other columns like Tname,TUtility....
For update statement TID has a value and works well. But for an insert statement I want the serial number(which is the TID column) to be automatically populated.
private void SaveData(DataGridView dgv)
{
using (SQLiteConnection conn = new SQLiteConnection(connString))
{
conn.Open();
dt = dt.GetChanges();
if (dt.Rows.Count > 0)
{
int dtlength = dt.Rows.Count;
DataRow[] arr = new DataRow[dtlength];
dt.Rows.CopyTo(arr, 0);
SQLiteCommand upCmd = new SQLiteCommand(
#"INSERT OR REPLACE
INTO
[Table1](
[TID],
[TName],
[TUtility],
[TType])values(#TID,#Tname,#TUtility,#TType),conn);
for (int i = 0; i < arr.Length; i++)
{
upCmd.Parameters.AddWithValue("#TID", Convert.ToInt32(arr[i]["SNo"]));
upCmd.Parameters.AddWithValue("#TName", arr[i]["Utility"].ToString());
upCmd.Parameters.AddWithValue("#TUtility", arr[i]["Plantname"].ToString());
upCmd.Parameters.AddWithValue("#TType", arr[i]["PlantType"].ToString())
da.UpdateCommand = upCmd;
this.da.UpdateCommand.ExecuteNonQuery();
}
How should I add this TID value in such a way that when the users inserts a new row, it should automatically put the serial number.
I mean: Suppose there are 4rows currently in the DGV. The DGV is in edit mode(*).I am adding a new row. Once the user tries to enter some data in the new row, there should be a serial number already populated.
Thank you
Sun
I am not sure if I understand your problem but why not just put NULL for TID when you do INSERT. Since TID is primary key, the sqlite will insert value automatically.
According to Sqlite FAQ it says this for primary key
whenever you insert a NULL into that column of the table, the NULL is
automatically converted into an integer which is one greater than the
largest value of that column over all other rows in the table, or 1 if
the table is empty.

Categories

Resources