I'm developing a windows service in C# and it accesses the database several times when files are dropped into a specific directory. Furthermore, I have a service_timer that runs every 5 minutes that also accesses the database. The issue then, is that when my service is processing a file and my service_timer is called, I end up getting an InvalidOperationError (There is already an open Data Reader).
Is there a way to create a new connection for to the database (on Microsoft SQL Server Express) so I can avoid this problem, or is there another common solution?
Thanks.
Here is the code of the function where the exception is being thrown:
DateTime start = DateTime.Now;
string SqlQuery = "SELECT COUNT (*) AS recCount FROM " + tableName + " " + whereclause;
Debug.WriteLine(thisMethod + " SqlQuery: " + SqlQuery);
myCommand = new SqlCommand(SqlQuery, this.SDB); //Execute Sql Statement
myCommand.ExecuteNonQuery();
// Create New Adapter
adapter = new SqlDataAdapter(myCommand);
adapter.SelectCommand = myCommand;
DataSet ds = new DataSet();
// Populate Adapter
adapter.Fill(ds);
foreach (DataTable dt in ds.Tables)
foreach (DataRow dr in dt.Rows)
{
recCount = Convert.ToInt32(dr["recCount"]);
}
The problem lies here
myCommand = new SqlCommand(SqlQuery, this.SDB);
You should create a new SQLConnection within the method instead of using a global.
SqlConnection newConn = new SqlConnection(connectionString);
newConn.Open();
myCommand = new SqlCommand(SqlQuery, newConn);
//Rest of logic
newConn.Close();
Related
I have 02 combo box as shown [Combo Boxes]
When i move back and forth for selection of items b/w Combo Boxes(Category and Model No.) i get the following error
enter image description here
My C# sharp code is given below
try
{
con.Open();
string CmdString = "select ProductID from Product where ModelNo='" + comboModel.SelectedItem.ToString() + "'";
SqlCommand cmd = new SqlCommand(CmdString, con);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt1 = new DataTable("Product");
sda.Fill(dt1);
foreach (DataRow dr in dt1.Rows)
{
txtProductID.Text = dr["ProductID"].ToString();
}
con.Close();
}
catch (Exception exp)
{
MessageBox.Show(exp.ToString());
con.Close();
}
Get rid of con.Open();. Obviously the connection was already open from an earlier operation somewhere else or a prior run of this code.
That being said, you should probably not be keeping connections open unless you need them, because you run the risk that they aren't ever closed properly. You should use the disposable pattern, like this:
using (var con = new SqlConnection(myConnStr))
{
// do your query, etc.
}
This will automatically close the connection and dispose of the resources.
Your connection is opened somewhere else. Try putting it into using block, this way it will be disposed of automatically and is best practice for connections:
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
string CmdString = "select ProductID from Product where ModelNo='" +
comboModel.SelectedItem.ToString() + "'";
SqlCommand cmd = new SqlCommand(CmdString, connection);
SqlDataAdapter sda = new SqlDataAdapter(cmd);
DataTable dt1 = new DataTable("Product");
sda.Fill(dt1);
foreach (DataRow dr in dt1.Rows)
{
txtProductID.Text = dr["ProductID"].ToString();
}
}
I write these code all are working fine but there is a warning coming that sanitize the sql parameter.
private DataSet ExcelToDataSet(string fileData)
{
DataSet ds = new DataSet();
string connectionString = GetConnectionString(fileData);
using (OleDbConnection conn = new OleDbConnection(connectionString))
{
conn.Open();
OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
// Get all Sheets in Excel File
DataTable dtSheet = conn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);
// Loop through all Sheets to get data
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
cmd = null;
conn.Close();
}
return (ds);
}
I have to sanitize the following line
cmd.CommandText = "SELECT * FROM [" + sheetName + "]";
Usually, when writing SQL Statements, you need to use parameters to pass the data from user input into the sql statement, to prevent SQL Injection attacks. That's why you get this warning. However, there is nothing you can do about it since it's impossible to parameterize identifiers in SQL, and you don't need to do it because you are not concatenating user input, and you are not running this query on a database, so even if you could use SQL injection, the worst you can do is corrupt a single file
UPDATE: I did not notice this was a OleDbConnection, the database you are connecting to may not have the same functionality to quote an identifier. I am leaving this answer here in case someone comes across this question and needs the same thing but for a SQL connection.
As the others have said, there is no need to worry about the warning in this case as the data is not coming from user data.
However everyone is wrong about the fact you cannot parameterize an identifier. You need to build the query dynamically server side and use the QUOTENAME function but it is possible.
foreach (DataRow dr in dtSheet.Rows)
{
string sheetName = dr["TABLE_NAME"].ToString();
if (!sheetName.EndsWith("$"))
continue;
// Get all rows from the Sheet
cmd.CommandText = #"
declare #sql nvarchar(114);
set #sql = N'select * from ' + quotename(#sheetname)
exec sp_executesql #sql
";
cmd.Parameters.Clear();
cmd.Parameters.Add("#sheetname", SqlDbType.NVarChar, 100).Value = sheetName;
DataTable dt = new DataTable();
dt.TableName = sheetName;
OleDbDataAdapter da = new OleDbDataAdapter(cmd);
da.Fill(dt);
ds.Tables.Add(dt);
}
This will generate a dynamic query that will safely escape the name of the table.
I have an openquery SQL script:
Select * from openquery([oak],'
SELECT LicenseKey, SUM(PaymentAmount)as Payments
FROM vw_ODBC_actv_Payments pt
WHERE MONTH(pt.EntryDate) = 2 and
YEAR(pt.EntryDate) = 2015
GROUP BY LicenseKey
')
When I run this from SSMS I can see that it returns expected n rows.
However when I'm firing this with the same connection properties to get the data in a DataSet for a C# console application:
SqlDataAdapter da = new SqlDataAdapter();
SqlCommand pcmd= new SqlCommand();
DataSet ds= new DataSet();
OpenConnection();
pcmd.Connection = new SqlConnection("Data source=IP adress of the server;Initial Catalog=master; user ID=***; password=***");
cmd.CommandText = "Select * from openquery([oak],'" +
"SELECT LicenseKey, SUM(PaymentAmount)as Payments" +
"FROM vw_ODBC_actv_Payments pt " +
"WHERE MONTH(pt.EntryDate) = 2 and" +
"YEAR(pt.EntryDate) = 2015" +
"GROUP BY LicenseKey')";
try
{
da.SelectCommand = pcmd;
da.Fill(ds); //here comes the error
}
catch (Exception ex)
{
throw new Exception("DBUtils.ExecuteReader():" + ex.Message);
}
I'm getting an error like this:
The provider indicates that the user did not have the permission to
perform the operation. Now I need to do something with this issue
I'm just learning about openquery. Can anybody guide?
Firstly you're not opening the connection anywhere in your code hence the error. Second clean up your code with the using block. So assuming the query works as required you can do something like.
using(SqlConnection con = new SqlConnection("Connection String Here"))
{
string myQuery = "Your Query";
using(SqlCommand cmd = new SqlCommand(myQuery, con))
{
using (SqlDataAdapter sda = new SqlDataAdapter())
{
con.Open();
sda.SelectCommand = cmd;
DataSet ds = new DataSet();
sda.Fill(ds);
}
}
}
Note: It would be a better if you stored the connectionString in your config file and read it in your code.
What is the error of this code
connect = new OleDbConnection(coo);
connect.Open();
command.Connection = connect;
DataTable dt = new DataTable();
OleDbDataAdapter ODA = new OleDbDataAdapter("SELECT * FROM Items where itemno = '" + textBox1.Text + "'", connect);
ODA.Fill(dt);
dataGridView1.DataSource = dt;
after I run it, this is what happened
"Data type mismatch in criteria expression"
What should I do?
itemno is integer, that is why you are getting the error, remove the single quotes around the value. But, More importantly, Use Parameters with your query. You are prone to SQL Injection
using (var connect = new OleDbConnection(coo))
{
using (OleDbCommand command = new OleDbCommand("SELECT * FROM Items where itemno = ?", connect))
{
command.Parameters.Add(new OleDbParameter("#p1", OleDbType.Integer)
{
Value = textBox1.Text
});
DataTable dt = new DataTable();
OleDbDataAdapter ODA = new OleDbDataAdapter(command);
ODA.Fill(dt);
dataGridView1.DataSource = dt;
}
}
Couple of things to add:
Enclose your Command and Connection object in using statement.
You don't have to explicitly open a connection with DataAdapter. It will open the connection to the database.
OleDB uses positional parameter instead of named parameter
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions must demonstrate a minimal understanding of the problem being solved. Tell us what you've tried to do, why it didn't work, and how it should work. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I am developing on web application that will get the excel file using FileUpload control in asp.net c#. Now when click on submit button, i want to insert the excel data into my database table. I have database in SQL-Server. The field of database table & excel file are same.I want to insert that excel's data into my database table. So how can i do this?
Others have mentioned using Excel interop to read the Excel file in the comments, but this is NOT safe to do for a web application that may have multiple users.
To get started, have a look at the Excel Data Reader project. I've used this several times for processing Excel files from a web application and it works quite well.
You can use OLEDB classes to read directly from Excel file using the Excel drivers in OleDbConnection. Get the data in a datatable and save it to database.
string connectString =
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=d:\\testit.xlsx;Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;\"";
OleDbConnection conn = new OleDbConnection(connectString);
OleDbDataAdapter da = new OleDbDataAdapter("Select * From [Sheet1$]", conn);
DataTable dt = new DataTable();
da.Fill(dt);
// Save your datatable records to DB as you prefer.
I've been testing NPOI as a replacement for another 3rd party Excel parsing library.
https://code.google.com/p/npoi/
So far it seems to work pretty well and have a very complete feature set. Of course, if all you need is very basic Excel data reading (and no writing), then the other DB connection style interfaces mentioned here should work well enough.
EDIT: added sample code
using( FileStream fs = new FileStream("file.xls", FileMode.Open, FileAccess.Read) )
{
HSSFWorkbook wb = new HSSFWorkbook(fs);
double value = wb.GetSheet("Sheet1").GetRow(1).GetCell(1).NumericCellValue;
// read other values as necessary.
}
try the following code . maybe its crude but it works
string connectString =
"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=c:\\data\\exceltest.xlsx;Extended Properties=\"Excel 12.0 Xml;HDR=YES;IMEX=1;\"";
OleDbConnection conn = new OleDbConnection(connectString);
OleDbDataAdapter da = new OleDbDataAdapter("Select * From [Sheet1$]", conn);
DataTable dt = new DataTable();
da.Fill(dt);
conn.Close();
SqlConnection sqlc = new SqlConnection(#"server=.\SQLEXPRESS;user id=sa;pwd=windows;database=exceltest");
sqlc.Open();
SqlCommand cmd = new SqlCommand("select * from table1", sqlc);
SqlDataAdapter sda = new SqlDataAdapter("select * from table1", sqlc);
sda.InsertCommand = new SqlCommand("insert into table1", sqlc);
DataTable dbset = new DataTable();
da.Fill(dbset);
SqlCommand cmdinsert = new SqlCommand();
cmdinsert.Connection = sqlc;
foreach (DataRow dsrc in dt.Rows)
{
string insertcommand = "insert into table1" + dbset.TableName + " ";
string cols = "";
string vals = "";
DataRow dr = dbset.NewRow();
foreach (DataColumn clm in dt.Columns)
{
dr[clm.ColumnName] = dsrc[clm.ColumnName].ToString(); ;
if (cols.Length > 0)
{
cols += ",[" + clm.ColumnName+"]";
}
else
{
cols = "["+clm.ColumnName+"]";
}
if (vals.Length > 0)
{
vals += "," + "'" + dsrc[clm.ColumnName].ToString() + "'";
}
else
{
vals = "'" + dsrc[clm.ColumnName].ToString() + "'";
}
}
insertcommand += "(" + cols + ") values("+vals+")";
cmdinsert.CommandText = insertcommand;
cmdinsert.ExecuteNonQuery();
insertcommand = "";
}
sqlc.Close();