I was working with an application that uses sql server database. I was trying to insert a row into a table as shown below. This table has a primary key 'prodNum'. It's auto-generating key.
When I try to insert a row to the table as shown below,in line intResult = oSglProdTableAdapt.Update(oCableRecDataSet, "ProdTable") I'm getting an exception:
{"Column 'prodNum' is read only."}
I'm not even setting value for 'prodNum' column while creating the datarow as you can see. But the update function trying to write the value for that column also.
I tried to insert using Insert query in sql management studio software. There It's working fine. So I assume that the issue is with my code. Is there anything I'm missing?
' a record does not exist for the new Cable Product
' therefore insert a new data row in the ProdTable table
' clear the DataSet
oCableRecDataSet.Clear()
' create the Data Row
Dim oDR As DataRow = oCableRecDataSet.Tables("ProdTable").NewRow()
' populate the datarow with values
'oDR("ProductIDNum") = 102
oDR("ProductID") = ProductID
oDR("DefinedDate") = DefinedDate
oDR("OperID") = OperID
oDR("CutsizeBased") = CutsizeBased
ProdTable.AddDRofProdTable(oDR)
' add the datarow to the dataset
oCableRecDataSet.Tables("ProdTable").Rows.Add(oDR)
' update the Database with values from Dataset with the Data adapter
intResult = oSglProdTableAdapt.Update(oCableRecDataSet, "ProdTable")
Public Sub AddDRofCableDef(ByRef oDR As DataRow)
oDR("Upper") = m_Upper
oDR("Spec") = m_Spec
oDR("IlUpper") = m_IlUpper
oDR("IlLower") = m_lIlLower
oDR("Spec") = m_Spec
oDR("MeanUpper") = m_MeanUpper
oDR("MeanLower") = m_MeanLower
oDR("MeanUL") = m_MeanUL
oDR("MeanLL") = m_MeanLL
oDR("SUL") = m_SUL
oDR("StartZone") = m_StartZone
End Sub
Stack Trace Follows:
at System.Data.DataRow.set_Item(DataColumn column, Object value) at
System.Data.DataRow.set_Item(String columnName, Object value) at
ACMS.DBCableRecordsCommands.OnRowUpdated(Object sender,
OleDbRowUpdatedEventArgs args) in
D:\Software\clsDBCableRecordsCommands.vb:line 956 at
System.Data.OleDb.OleDbRowUpdatedEventHandler.Invoke(Object sender,
OleDbRowUpdatedEventArgs e) at
System.Data.OleDb.OleDbDataAdapter.OnRowUpdated(RowUpdatedEventArgs
value) at System.Data.Common.DbDataAdapter.Update(DataRow[]
dataRows, DataTableMapping tableMapping) at
System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable
dataTable, DataTableMapping tableMapping) at
System.Data.Common.DbDataAdapter.Update(DataSet dataSet, String
srcTable) at
ACMS.DBCableRecordsCommands.insertCableRecord(DBCableRecords Cable) in
D:\Software\clsDBCableRecordsCommands.vb:line 251
UPDATE
One thing I noticed when I checked the generated datarow it has the ProdNum(Primary key) calculated, even though I'm not initializing that value. That may be the reason why sql server is not accepting. How to stop generation of primary key by datarow?
I assume that "oCableRecDataSet" is the name of your DataSet, and the DataSet contains only one Table, so you can try this:
oCableRecDataSet.Tables(0).Columns("produNum").ReadOnly = false
intResult = oSglProdTableAdapt.Update(oCableRecDataSet, "ProdTable")
Related
I am using the following code to export data from excel to Sql server database. What is going on with this code is, its importing complete data into the database.
[HttpPost]
public ActionResult Importexcel()
{
if (Request.Files["FileUpload1"].ContentLength > 0)
{
string extension = System.IO.Path.GetExtension(Request.Files["FileUpload1"].FileName);
string path1 = string.Format("{0}/{1}", Server.MapPath("~/Content/UploadedFolder"), Request.Files["FileUpload1"].FileName);
if (System.IO.File.Exists(path1))
System.IO.File.Delete(path1);
Request.Files["FileUpload1"].SaveAs(path1);
string sqlConnectionString = #"Data Source=xyz-101\SQLEXPRESS;Database=PracDB;Trusted_Connection=true;Persist Security Info=True";
string excelConnectionString = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + path1 + ";Extended Properties=Excel 12.0;Persist Security Info=False";
OleDbConnection excelConnection = new OleDbConnection(excelConnectionString);
OleDbCommand cmd = new OleDbCommand("Select [ID],[Name],[Designation] from [Sheet1$]", excelConnection);
excelConnection.Open();
OleDbDataReader dReader;
dReader = cmd.ExecuteReader();
SqlBulkCopy sqlBulk = new SqlBulkCopy(sqlConnectionString);
sqlBulk.DestinationTableName = "Excel_Table";
sqlBulk.WriteToServer(dReader);
excelConnection.Close();
}
return RedirectToAction("Index");
}
How to check that any particular record already exist in the database or not. If not then Insert the record into the databse else it should not.
Thanks in Advance !
Since your target is SQL Server, you can use this to your advantage.
What I would do is read the data from the excel into a DataTable (instead of using a DataReader you can use a DataAdapter), Send that DataTable to a stored procedure in the SQL server, and handle the insert there. In order to sand a data table to a stored procedure you first need to create a Table-value user defined type in your sql server, like this:
CREATE TYPE MyType AS TABLE
(
Id int,
Name varchar(20), -- use whatever length best fitted to your data
Designation varchar(max) -- use whatever length best fitted to your data
)
Then you can write a simple stored procedure with an argument of this type:
CREATE PROCEDURE InsertDataFromExcel
(
#ExcelData dbo.MyType readonly -- Note: readonly is a required!
)
AS
INSERT INTO MyTable(Id, Name, Designation)
SELECT a.Id, a.Name, a.Designation
FROM #ExcelData a LEFT JOIN
MyTable b ON(a.Id = b.Id)
WHERE b.Id IS NULL -- this condition with the left join ensures you only select records that has different id values then the records already in your database
in order to send this parameter to the stored procedure from your c# code you will have to use a SqlCommand object and add the DataTable as a parameter, something like this:
using(SqlConnection Con = new SqlConnection(sqlConnectionString))
{
using(SqlCommand InsertCommand = new SqlCommand("InsertDataFromExcel", Con))
{
SqlParameter MyParam = new SqlParameter("#ExcelData", SqlDBType.Structured);
MyParam.Value = MyDataTable; // this is the data table from the
InsertCommand.Parameters.Add(MyParam);
Con.Open();
InsertCommand.ExecuteNoQuery();
Con.Close();
}
}
Note: Code was writen directly here, some errors might be found.
Okay this problem of mine is a little bit tricky for the past months now.
SUMMARY: When I only have 5 columns in my Access Database my code successfully inserts the new row. But when I add another column in my access database (that will be 6 columns now) I encounter
Syntax Error INSERT INTO Statement
Code:
Dim cb As New OleDb.OleDbCommandBuilder(SYSTEM_MainClient.dbda)
Dim dsNewRow As DataRow
dsNewRow = SYSTEM_MainClient.DataSet.Tables("Database").NewRow()
dsNewRow.Item("First_Name") = TXT_FirstName.Text
dsNewRow.Item("Last_Name") = TXT_Surname.Text
dsNewRow.Item("StudentID") = CInt(TXT_StudentID.Text)
dsNewRow.Item("Middle_Name") = TXT_MiddleName.Text
dsNewRow.Item("College") = TXT_College.Text
SYSTEM_MainClient.DataSet.Tables("Database").Rows.Add(dsNewRow)
SYSTEM_MainClient.dbda.Update(SYSTEM_MainClient.DataSet, "Database")
MsgBox("New Record added to the Database")
My database cColumns:
"StudentID" (primary key),
"First_Name", "Last_Name", "Middle_Name"
"College"
RESULT: This will work okay, and new record is added into the database.
Because there is only 5 columns.
BUT IF I EXCEED:
Code:
Dim cb As New OleDb.OleDbCommandBuilder(SYSTEM_MainClient.dbda)
Dim dsNewRow As DataRow
dsNewRow = SYSTEM_MainClient.DataSet.Tables("Database").NewRow()
dsNewRow.Item("First_Name") = TXT_FirstName.Text
dsNewRow.Item("Last_Name") = TXT_Surname.Text
dsNewRow.Item("StudentID") = CInt(TXT_StudentID.Text)
dsNewRow.Item("Middle_Name") = TXT_MiddleName.Text
dsNewRow.Item("College") = TXT_College.Text
dsNewRow.Item("Section") = TXT_Section.Text 'I added a section insert
SYSTEM_MainClient.DataSet.Tables("Database").Rows.Add(dsNewRow)
SYSTEM_MainClient.dbda.Update(SYSTEM_MainClient.DataSet, "Database")
MsgBox("New Record added to the Database")
My database columns:
"StudentID" (primary key)
"First_Name", "Last_Name", "Middle_Name"
"College", "Section".
It will return an error
Syntax Error INSERT INTO Statement
It's like it can only insert not more than 5 column values, I think the problem is access not VB itself.
I hope you understand my problem, please help me It's my problem for months now, I searched the forums and Googled it, still can't find the answer.
Thank you so much!
This happens almost universally because one or more column names are reserved words or contain spaces or other special characters. In your case I suspect that "section" is a reserved word.
The solution is to set the .QuotePrefix and .QuoteSuffix properties of the OleDbCommandBuilder object to escape all column names. For Access, set them to "[" and "]" respectively.
Is it possible to populate a temp table using AseBulkCopy.WriteToServer?
I am calling the below method twice in my test app: firstly with a non-temp table and secondly with a temp table. The code runs fine with the non-temp table, but when trying to populate a temp table the error:
Incorrect syntax near ','.
is raised.
In both cases the target and source tables have just a single column, defined as an INT with the same name.
I have tried using a DataTable and an IDataReader as the source of the data and both result in the same error being raised.
I have tried using both "EnableBulkLoad=1" and "EnableBulkLoad=2" in the connection string.
I have tried using both the raw temp table name and the name prefixed with "dbo."
The data to be loaded is a single int value (ie, 1 row, 1 column) although it also happens if have longer rows or multiple rows.
It's worth noting that I can insert data into the temp table (using AseCommand.ExecuteNonQuery) and can execute a 'SELECT COUNT (1)' from the temp table (using AseCommand.ExecuteScalar) successfully.
Here is the code:
private static void BulkCopyInsertIntoTable(string tableName)
{
IDataReader dataSource = null;
SqlConnection sourceConnection = null;
MssqlCommand.GetDataReader(SqlServerConnectionString, out sourceConnection, out dataSource);
AseConnection targetConnection = new AseConnection(SybaseConnectionString);
try
{
targetConnection.Open();
AseCommand cmd = new AseCommand();
AseBulkCopy blk = new AseBulkCopy(targetConnection);
blk.DestinationTableName = tableName;
//blk.ColumnMappings.Clear();
//blk.ColumnMappings.Add(new AseBulkCopyColumnMapping(0, 0));//Doesn't make any difference with a datasource, causes an error to be raised with a datatable.
Console.WriteLine("bulkcopy insert into the table " + tableName + " ..starting: datasource");
//blk.WriteToServer(dataSource);
Console.WriteLine("bulkcopy insert into the table " + tableName + " ..starting: datatable");
blk.ColumnMappings.Clear();
DataTable dt = SybaseCommand.GetFakeDataTable(); ;
blk.WriteToServer(dt);
}
catch (AseException ex)
{
Console.WriteLine(ex.Message);
}
finally
{
targetConnection.Dispose();
Console.WriteLine("bulkcopy insert into the table " + tableName + " ..ended");
}
}
Firstly, is it possible to populate a temp table using WriteToServer?
Assuming it is, what might I being doing wrong?
UPDATE:
When I change the line
blk.DestinationTableName = tableName;
to
blk.DestinationTableName = "XXXX";
I get the same error, so are there rules about how the temp table is named when using WriteToServer? The value of tableName is what I was using for the direct INSERT and SELECT COUNT(1) queries so I expected it to be correct.
Thanks
In my experience, the answer is no, you can't use AseBulkCopy.WriteToServer to populate a temporary table.
I use Sql server 2008 to store my data,and the table structure like that
index float not null,
type int not null,
value int not null,
and the (index,type) is unique.there are not two datas has the same index and the same type.
So when I insert the data to the table, I have to check the (index,type) pair whether in the table already, if it exists I use update statement, otherwise, I insert it directly.but I think this is not a efficient way,because:
Most of the data' index-type pair is not existed int the table.so the select operation is waste, especially the table is huge.
When I use C# or other CLR language to insert the data, I can't use batch copy or batch insert.
is there any way to overwrite the data directly without check whether it is existed in the table?
If you want to update OR insert the data, you need to use merge:
merge MyTable t using (select #index index, #type type, #value value) s on
t.index = s.index
and t.type = s.type
when not matched insert (index, type value) values (s.index, s.type, s.value)
when matched update set value = s.value;
This will look at your values and take the appropriate action.
To do this in C#, you have to use the traditional SqlClient:
SqlConnection conn = new SqlConnection("Data Source=dbserver;Initial Catalog=dbname;Integrated Security=SSPI;");
SqlCommand comm = new SqlCommand();
conn.Open();
comm.Connection = conn;
//Add in your values here
comm.Parameters.AddWithValue("#index", index);
comm.Parameters.AddWithValue("#type", type);
comm.Parameters.AddWithValue("#value", value);
comm.CommandText =
"merge MyTable t using (select #index index, #type type, #value value) s on " +
"t.index = s.index and t.type = s.type " +
"when not matched insert (index, type value) values (s.index, s.type, s.value) " +
"when matched update set value = s.value;"
comm.ExecuteNonQuery();
comm.Dispose();
conn.Close();
conn.Dispose();
You should make (index, type) into a composite primary key (aka compound key).
This would ensure that the table can only even have unique pairs of these (I am assuming the table does not have a primary key already).
If the table does have a primary key, you can add a UNIQUE constraint onto those columns with similar effect.
Once defined, this means that any attempt to insert a duplicate pair would fail.
Other answers recommend constraints. Creating constraints just means you will be executing insert statements that trigger errors. The next step (after having created the constraints) is something like INSERT ON DUPLICATE KEY UPDATE, which apparently does have an Sql Server equivalent.
I have a table in C#, the data is coming from an Excel file. I need this data to be inserted into a SQL Server 2000 table. I am not to use stored procedures. How do I program it? Any help would be appreciated.
Do you have a DataTable ?
You'd need something like:
// set up connection to your database
using (SqlConnection con = new SqlConnection("your-connection-string-here"))
{
// define the INSERT statement - of course, I don't know what your table name
// is and which and how many fields you want to insert - adjust accordingly
string insertStmt =
"INSERT INTO dbo.YourTable(field1, field2, field3) " +
"VALUES(#field1, #field2, #field3)";
// create SqlCommand object
using (SqlCommand cmd = new SqlCommand(insertStmt, con))
{
// set up the parameters - again: I don't know your parameter names
// nor the parameters types - adjust to your needs
cmd.Parameters.Add("#field1", SqlDbType.Int);
cmd.Parameters.Add("#field2", SqlDbType.VarChar, 100);
cmd.Parameters.Add("#field3", SqlDbType.VarChar, 250);
// open connection
con.Open();
// iterate over all the Rows in your data table
foreach (DataRow row in YourDataTable.Rows)
{
// assign the values to the parameters, based on your DataRow
cmd.Parameters["#field1"].Value = Convert.ToInt32(row["columnname1"]);
cmd.Parameters["#field2"].Value = row["columnname2"].ToString();
cmd.Parameters["#field3"].Value = row["columnname3"].ToString();
// call INSERT statement
cmd.ExecuteNonQuery();
}
// close connection
con.Close();
}
}
Of course, this has no error checking whatsoever, you will need to add some of that yourself (try....catch and so on). But basically, that's the way I would do it, if I can't use stored procedures.
use System.Data.SqlClient.SqlCommand