I'm familiar with SQL Server but new to Oracle. I'm working on doing a bulk insert or update using the Array technique I've found in some examples. However, I must be doing this incorrect because I'm getting errors about "invalid table.column". I have a feeling it has to do with the way I'm trying to assign parameter names in the in-line SQL and command parameters. In the example I've seen they use numeric values for the parameters like ":1, :2, :3" but if possible I would like to use ":paramtername1, :parametername2, :parametername3".
Here is what I'm doing
sbQuery.Append("update SAP_EMPLOYEE set ");
sbQuery.Append(" EMP_ID = :p_EmployeeId, EVENT_FROM_DT = :p_EventFromDate, EVENT_TYP = :p_EventType, EVENT_RSN = :p_EventRsn,");
sbQuery.Append(" where Emp = :p_Employee");
Then I create arrays to add the values to
string[] arrEmployee = new string[listEmployee.Count];
string[] arrEmployeeId = new string[listEmployee.Count];
DateTime[] arrEventFromDt = new DateTime[listEmployee.Count];
string[] arrEventTyp = new string[listEmployee.Count];
string[] arrEventRsn = new string[listEmployee.Count];
Populate the arrays
int i = 0;
foreach (SAP_EMPLOYEE item in listEmployee)
{
arrEmployee[i] = item.EMP;
arrEmployeeId[i] = item.EMP_ID;
if(item.EVENT_FROM_DT.HasValue)
{
arrEventFromDt[i] = item.EVENT_FROM_DT.Value;
}
arrEventTyp[i] = item.EVENT_TYP;
arrEventRsn[i] = item.EVENT_RSN;
i++;
}
Then call the connection, cmd, query
OracleConnection objConnection = new OracleConnection(connString);
using (objConnection)
{
objConnection.Open();
//create Oracle parameters and pass arrays of data
OracleParameter p_Employee = new OracleParameter();
p_Employee.OracleDbType = OracleDbType.Varchar2;
p_Employee.Value = arrEmployee;
OracleParameter p_EmployeeId = new OracleParameter();
p_EmployeeId.OracleDbType = OracleDbType.Varchar2;
p_EmployeeId.Value = arrEmployeeId;
OracleParameter p_EventFromDate = new OracleParameter();
p_EventFromDate.OracleDbType = OracleDbType.Date;
p_EventFromDate.Value = arrEventFromDt;
OracleParameter p_EventType = new OracleParameter();
p_EventType.OracleDbType = OracleDbType.Char;
p_EventType.Value = arrEventTyp;
OracleParameter p_EventRsn = new OracleParameter();
p_EventType.OracleDbType = OracleDbType.Char;
p_EventType.Value = arrEventRsn;
OracleCommand objCmd = objConnection.CreateCommand();
objCmd.CommandText = sbQuery.ToString();
objCmd.ArrayBindCount = arrEmployee.Length;
objCmd.Parameters.Add(p_Employee);
objCmd.Parameters.Add(p_EmployeeId);
objCmd.Parameters.Add(p_EventFromDate);
objCmd.Parameters.Add(p_EventType);
objCmd.Parameters.Add(p_EventRsn);
objCmd.ExecuteNonQuery();
}
Related
I need help on determining what cause the error of my code.
"Conversion failed when converting the varchar value 'Undergraduate' to data type int." when i hit the ADD Button.
I'm struggling to find what went wrong. It worked at first but suddenly, the error alway occur.
This is the full code;
private void btnadd_Click(object sender, EventArgs e)
{
using (SqlConnection conncurr = new SqlConnection(Properties.Settings.Default.connectionstring))
using (SqlCommand cmdcurr = new SqlCommand("curriculumadd", conncurr))
{
try
{
conncurr.Open();
var newaccountparam1 = new SqlParameter("#dccode", SqlDbType.VarChar);
var newaccountparam2 = new SqlParameter("#dcdesc", SqlDbType.VarChar);
var newaccountparam3 = new SqlParameter("#currtitle", SqlDbType.VarChar);
var newaccountparam4 = new SqlParameter("#units", SqlDbType.Int);
var newaccountparam5 = new SqlParameter("#labunits", SqlDbType.Int);
var newaccountparam6 = new SqlParameter("#lecunits", SqlDbType.Int);
var newaccountparam7 = new SqlParameter("#yearlevel", SqlDbType.Int);
var newaccountparam8 = new SqlParameter("#sem", SqlDbType.Int);
var newaccountparam9 = new SqlParameter("#labhrs", SqlDbType.Int);
var newaccountparam10 = new SqlParameter("#lechrs", SqlDbType.Int);
var newaccountparam11 = new SqlParameter("#acadlevel", SqlDbType.Int);
var newaccountparam12 = new SqlParameter("#subjcode", SqlDbType.VarChar);
var newaccountparam13 = new SqlParameter("#subjdesc", SqlDbType.VarChar);
var newaccountparam14 = new SqlParameter("#subjcat", SqlDbType.VarChar);
var newaccountparam15 = new SqlParameter("#curreffectvty", SqlDbType.VarChar);
newaccountparam1.Value = txtcoursecode.Text;
newaccountparam2.Value = txtdcourse.Text;
newaccountparam3.Value = currtitle;
newaccountparam4.Value = totalunits;
newaccountparam5.Value = txtlabunits.Text;
newaccountparam6.Value = txtlecunits.Text;
newaccountparam7.Value = yearlevel;
newaccountparam8.Value = semestr;
newaccountparam9.Value = labhrs;
newaccountparam10.Value = lecthrs;
newaccountparam11.Value = acadlevel;
newaccountparam12.Value = txtsubjcode.Text;
newaccountparam13.Value = txtdesctitle.Text;
newaccountparam14.Value = cmbsubjfield.Text;
newaccountparam15.Value = txteffectivity.Text;
cmdcurr.Parameters.Add(newaccountparam1);
cmdcurr.Parameters.Add(newaccountparam2);
cmdcurr.Parameters.Add(newaccountparam3);
cmdcurr.Parameters.Add(newaccountparam4);
cmdcurr.Parameters.Add(newaccountparam5);
cmdcurr.Parameters.Add(newaccountparam6);
cmdcurr.Parameters.Add(newaccountparam7);
cmdcurr.Parameters.Add(newaccountparam8);
cmdcurr.Parameters.Add(newaccountparam9);
cmdcurr.Parameters.Add(newaccountparam10);
cmdcurr.Parameters.Add(newaccountparam11);
cmdcurr.Parameters.Add(newaccountparam12);
cmdcurr.Parameters.Add(newaccountparam13);
cmdcurr.Parameters.Add(newaccountparam14);
cmdcurr.Parameters.Add(newaccountparam15);
cmdcurr.CommandType = CommandType.StoredProcedure;
cmdcurr.ExecuteNonQuery();
}
finally
{
conncurr.Close();
conncurr.Dispose();
userlogsmonitor.ActiveForm.Refresh();
}
}
}
Code for converting string to integer;
private void cmbacadlevel_SelectedIndexChanged(object sender, EventArgs e)
{
switch (cmbacadlevel.SelectedItem.ToString().Trim())
{
case "Undergraduate":
acadlevel = 1;
break;
case "Masteral":
acadlevel = 2;
break;
case "Doctorate":
acadlevel = 3;
break;
case "Senior High School":
acadlevel = 4;
break;
}
I tried editing the code but it seems not lucky enough. Can you please scrutinize my code and try to give an idea on how to deal with it?
Verify following things
Order and type of parameter is same as in the stored procedure
Either use breakpoint to verify values of int parameters
Or use SQL Server Profiler to to check if int parameters have valid values.
I am trying to get a little tool to work, for our little company.
This should fill data from a DataGridView into a SQL Server Standard database.
Reading out the SQL table is working fine, but I can't get the tool to write the values.
I get the error mentioned in the title.
Here the code:
var kdNummer = new SqlParameter("Kundennummer", SqlDbType.Int);
var kdName = new SqlParameter("Kundenname", SqlDbType.VarChar);
var kdMail = new SqlParameter("Kundenmail", SqlDbType.VarChar);
var kdTele = new SqlParameter("Telefon", SqlDbType.VarChar);
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("Data Source=;Initial Catalog=updatedb;User ID=;Password="))
{
updatedb.Open();
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
using(SqlCommand NrDaten = new SqlCommand(kdquery, updatedb))
{
kdNummer.Value = dataGridView1.Rows[i].Cells["Kundennummer"].Value;
NrDaten.Parameters.Add(kdNummer);
NrDaten.ExecuteNonQuery();
}
using (SqlCommand NameDaten = new SqlCommand(kdquery, updatedb))
{
kdName.Value = dataGridView1.Rows[i].Cells["Kundenname"].Value;
NameDaten.Parameters.Add(kdName);
NameDaten.ExecuteNonQuery();
}
using (SqlCommand MailDaten = new SqlCommand(kdquery, updatedb))
{
kdMail.Value = dataGridView1.Rows[i].Cells["Kundenmail"].Value;
MailDaten.Parameters.Add(kdMail);
MailDaten.ExecuteNonQuery();
}
using (SqlCommand TeleDaten = new SqlCommand(kdquery, updatedb))
{
kdTele.Value = dataGridView1.Rows[i].Cells["Telefon"].Value;
TeleDaten.Parameters.Add(kdTele);
TeleDaten.ExecuteNonQuery();
}
}
updatedb.Close();
}
Your query requires 4 parameters, but you're always only setting one (also please note that in the SqlParameter you need to have the # sign as well). Thus you get an error about missing parameters. Your code should probably look like this:
var kdNummer = new SqlParameter("#Kundennummer", SqlDbType.Int);
var kdName = new SqlParameter("#Kundenname", SqlDbType.VarChar);
var kdMail = new SqlParameter("#Kundenmail", SqlDbType.VarChar);
var kdTele = new SqlParameter("#Telefon", SqlDbType.VarChar);
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("..."))
{
updatedb.Open();
using (SqlCommand insert = new SqlCommand(kdquery, updatedb))
{
insert.Parameters.Add(kdName);
insert.Parameters.Add(kdNummer);
insert.Parameters.Add(kdMail);
insert.Parameters.Add(kdTele);
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
kdName.Value = dataGridView1.Rows[i].Cells["Kundenname"].Value;
kdNummer.Value = dataGridView1.Rows[i].Cells["Kundennummer"].Value;
kdMail.Value = dataGridView1.Rows[i].Cells["Kundenmail"].Value;
kdTele.Value = dataGridView1.Rows[i].Cells["Telefon"].Value;
insert.ExecuteNonQuery();
}
}
}
Or even shorter:
string kdquery = "INSERT INTO Kunden VALUES (#Kundennummer, #Kundenname, #Kundenmail, #Telefon)";
using (SqlConnection updatedb = new SqlConnection("..."))
{
updatedb.Open();
for (int i = 0;i<dataGridView1.Rows.Count;i++)
{
using (SqlCommand insert = new SqlCommand(kdquery, updatedb))
{
insert.Parameters.AddWithValue("#Kundenname", dataGridView1.Rows[i].Cells["Kundenname"].Value);
insert.Parameters.AddWithValue("#Kundennummer", dataGridView1.Rows[i].Cells["Kundennummer"].Value);
insert.Parameters.AddWithValue("#Kundenmail", dataGridView1.Rows[i].Cells["Kundenmail"].Value);
insert.Parameters.AddWithValue("#Telefon", dataGridView1.Rows[i].Cells["Telefon"].Value);
insert.ExecuteNonQuery();
}
}
}
EDIT: I modified the long version of the code for maximum re-use of instances. Otherwise you get the errors mentioned in your comment.
[WebMethod]
public List<reports> getMyReports( int user_id )
{
string cs = ConfigurationManager.ConnectionStrings["ReportDB"].ConnectionString;
using (SqlConnection con = new SqlConnection(cs))
{
SqlCommand cmd = new SqlCommand("getAllReportsByUserID", con);
cmd.CommandType = CommandType.StoredProcedure;
List<reports> repers = new List<reports>();
//users[][] liser = new users[][];
SqlParameter user_id_parameter = new SqlParameter("#user_id", user_id);
cmd.Parameters.Add(user_id_parameter);
reports report = new reports();
con.Open();
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
report.id = Convert.ToInt32(reader["id"]);
report.title = reader["title"].ToString();
report.description = reader["description"].ToString();
report.anonymous = (bool)reader["anonymous"];
report.location = reader["location"].ToString();
report.status = reader["status"].ToString();
report.category = reader["category"].ToString();
report.date = (DateTime)reader["date"];
report.picture_url = reader["picture_url"].ToString();
report.admin_id = Convert.ToInt32(reader["admin_id"]);
repers.Add(report);
}
return repers;
}
}
I have the top function that calls the following stored procedure:
CREATE Proc [dbo].[getAllReportsByUserID]
#user_id int
as
Begin
Select
id,
title,
description,
anonymous,
location,
status,
category,
date,
picture_url,
admin_id
from reports
where user_id = #user_id
End
I have tested the procedure individually and it works fine. Yet, when I test the WebService created above I get a list with the last value duplicated along the whole list.
Can someone please help me figure out why do I get the same (last)value repeated over and over again?
By creating the report object before the loop and reusing it repeatedly, you insert a reference to that same object multiple times in your list.
You should create the report object inside your loop:
SqlDataReader reader = cmd.ExecuteReader();
while (reader.Read())
{
reports report = new reports();
report.id = Convert.ToInt32(reader["id"]);
report.title = reader["title"].ToString();
report.description = reader["description"].ToString();
report.anonymous = (bool)reader["anonymous"];
report.location = reader["location"].ToString();
report.status = reader["status"].ToString();
report.category = reader["category"].ToString();
report.date = (DateTime)reader["date"];
report.picture_url = reader["picture_url"].ToString();
report.admin_id = Convert.ToInt32(reader["admin_id"]);
repers.Add(report);
}
return repers;
when i am executing the code i am getting the exception in frmtime is
System.IndexOutOfRangeException: Index was outside the bounds of the
array
public IList<ExamSeatAllotmentEntity> GetAttendence1(string frmtime, string totime, DateTime date, int RoomNo)
{
List<ExamSeatAllotmentEntity> ObjTestList = new List<ExamSeatAllotmentEntity>();
//List<QuestionTypeEntity> ObjQTList = new List<QuestionTypeEntity>();
SqlParameter[] Parms = new SqlParameter[1];
Parms[0] = new SqlParameter("#RoomNo", SqlDbType.Int);
Parms[0].Value = RoomNo;
Parms[1] = new SqlParameter("#FromTime", SqlDbType.Time);
Parms[1].Value = frmtime;
Parms[2] = new SqlParameter("#Totime", SqlDbType.Time);
Parms[2].Value = totime;
Parms[3] = new SqlParameter("#Date", SqlDbType.DateTime);
Parms[3].Value = date;
DataSet dsTest = SqlHelper.ExecuteDataset(SqlHelper.connString, CommandType.StoredProcedure, SQL_PROC_GET_Attendence1, Parms);
if (dsTest != null && dsTest.Tables.Count == 1)
{
ObjTestList = (from test in dsTest.Tables[0].AsEnumerable()
select new ExamSeatAllotmentEntity()
{
// CourseID = test.Field<int>("CourseID"),
StudentId = test.Field<int>("StudentId"),
Fname = test.Field<string>("Fname"),
SeatNo = test.Field<string>("SeatNo"),
Attendence = test.Field<string>("Attendence")
}).ToList<ExamSeatAllotmentEntity>();
}
return ObjTestList;
}
new SqlParameter[1]
You just made an array that can only hold one item.
This would be the problem:
SqlParameter[] Parms = new SqlParameter[1];
You are specifying a length of 1 element: Parms[0]
Correct the size of the array to allow 4 elements:
SqlParameter[] Parms = new SqlParameter[4];
In case you want to add more parameters, you might want to create a list and then transform via ToArray().
Change
SqlParameter[] Parms = new SqlParameter[1];
to
SqlParameter[] Parms = new SqlParameter[4];
I am tryign to do bulk inserts/updates efficiently from c# code to oracle database.
If I done it by statement, then it doesn’t take much time.
I am using the ODP.NET
Currently insert of 6000 records via below stored proc is taking 15 mins.
I have to use this stored proc, because it generates unique user_id.
Is this proc doing auto-commit ? Is there any autocommit setting I should turn off ?
Please suggest ways to do it efficiently.
CREATE OR REPLACE
PROCEDURE sbx_staging_insert_user(client IN varchar2,
username IN varchar2,
comm_type IN varchar2,
email_addr IN varchar2,
buddy_name IN varchar2,
--default_flag IN char,
user_id OUT INT)
AS
BEGIN
select sbx_staging_user_id_seq.nextval into user_id from dual;
insert into sbx_staging_user
(user_id,
client,
username,
comm_type,
email_addr,
buddy_name,
default_flag)
values
(user_id,
client,
username,
comm_type,
email_addr,
buddy_name,
'Y');
end sbx_staging_insert_user;
and C# code is:
cmd.Transaction = conn.BeginTransaction();
cmd.CommandType = CommandType.Text;
cmd.CommandText = "sbx_staging_insert_user";
cmd.CommandType = CommandType.StoredProcedure;
var userClientParam = new OracleParameter(":client", OracleDbType.Varchar2);
var usernameParam = new OracleParameter(":username", OracleDbType.Varchar2);
var commTypeParam = new OracleParameter(":comm_type", OracleDbType.Varchar2);
var defaultParam = new OracleParameter(":default_flag", OracleDbType.Char) { Size = 1};
var emailParam = new OracleParameter(":email_addr", OracleDbType.Varchar2) { IsNullable = true };
var buddyParam = new OracleParameter(":buddy_name", OracleDbType.Varchar2) { IsNullable = true };
var userIdParam = new OracleParameter(":user_id", OracleDbType.Int32) { Direction = ParameterDirection.Output };
cmd.Parameters.Add(userClientParam);
cmd.Parameters.Add(usernameParam);
cmd.Parameters.Add(commTypeParam);
//cmd.Parameters.Add(defaultParam);
cmd.Parameters.Add(emailParam);
cmd.Parameters.Add(buddyParam);
cmd.Parameters.Add(userIdParam);
var cuList = new List<string>(Users.Count);
var uList = new List<string>(Users.Count);
var ctList = new List<string>(Users.Count);
var dfList = new List<char>(Users.Count);
var eaList = new List<string>(Users.Count);
var bnList = new List<string>(Users.Count);
var uiList = new List<decimal>(Users.Count);
int loopCnt = 0;
foreach (var ud in Users)
{
cuList.Add(ud.User.Client);
uList.Add(ud.User.Username);
ctList.Add(ud.User.CommType);
dfList.Add(ud.User.Default ? 'Y' : 'N');
eaList.Add(ud.User.Email);
bnList.Add(ud.User.BuddyName);
uiList.Add(-1);
}
userClientParam.Value = cuList.ToArray();
usernameParam.Value = uList.ToArray();
commTypeParam.Value = ctList.ToArray();
//defaultParam.Value = dfList.ToArray();
emailParam.Value = eaList.ToArray();
buddyParam.Value = bnList.ToArray();
userIdParam.Value = uiList.ToArray();
cmd.ArrayBindCount = cuList.Count;//Users.Count;//
cmd.ExecuteNonQuery();
cmd.Transaction.Commit();
Try something like this (untested, shortened for brevity):
public void insertRows()
{
if (Users.Count > 0)
{
OracleTransaction trans=_conn.BeginTransaction();
try
{
// create insert statement with bind vars
Stringbuilder sb = new Stringbuilder();
sb.Append("INSERT into sbx_staging_user(");
sb.Append("client,");
sb.Append("username,");
sb.Append("user_id");
sb.Append(") VALUES (");
sb.Append(":client,");
sb.Append(":username,");
sb.Append("seq_user_id.nextval");
sb.Append(") ");
OracleCommand cmd = new OracleCommand(sb.ToString(), _conn);
string[] ary_client = new string[Users.Count];
string[] ary_username = new string[Users.Count];
for (int i=0; i<Users.Count; i++)
{
User row=Users[i];
ary_client[i]=row.client;
ary_username[i]=row.username;
}
// prepare bind vars(bind in bulk using arrays)
OracleParameter prm=new OracleParameter();
cmd.Parameters.Clear();
cmd.ArrayBindCount=Users.Count;
cmd.BindByName=true;
prm=new OracleParameter("client", OracleDbType.Varchar2); prm.Value=ary_client; cmd.Parameters.Add(prm);
prm=new OracleParameter("username", OracleDbType.Varchar2); prm.Value=ary_username; cmd.Parameters.Add(prm);
cmd.ExecuteNonQuery();
trans.Commit();
trans.Dispose();
}
catch {
trans.Rollback();
trans.Dispose();
throw;
}
}
}
Maybe you should moove the bulk logic to the plsql.
See an example here:
http://dotnetslackers.com/articles/ado_net/BulkOperationsUsingOracleDataProviderForNETODPNET.aspx