I have tried various forms of the following method to get the next sequence value from an Oracle DB in my asp.net app. The sql statement works fine in Toad (11g). The sql statement includes "Select ... myschema.mySeq.nextval ... from dual. But the error I receive when I get to cmd.ExecuteNonQuery() -- the error is:
>
Exception Details: Oracle.DataAccess.Client.OracleException: ORA-00942: table or view does not exist
<<
Authentication is a very big deal at the place where I am at. Is this a data Access problem or is something incorrect with my method (below)? If something is incorrect with the code below what is the correction I need to make? Note: the app (big app) has hundreds of calls to SPs (which all work fine), so I basically copied the connection string code and used a constant (like they do throughout the app). If I use an SP this works, but I want to not use an SP just straight forward Ado.Net. What is the fix?
public int getNextPositionSequence(string userSeq)
{
OracleConnection conn = new OracleConnection(DaoHelper.GetConnectionString("AuthenticatedOracleConnectionString"));
conn.Open();
conn.ClientId = userSeq;
string sql = "SELECT ddtms.position_seq.nextval from dual";
OracleCommand cmd = new OracleCommand(sql, conn);
object s = cmd.ExecuteNonQuery(); //<<<--- crashes here
conn.Close();
return 1;
}
Related
I am trying to setup my .NET 4.7.1 program that is connecting to a MySQL database 8.0 to use the minimum privileges to run.
The .NET program is using MySql.Data to make connection. The minimum right for a user to execute a stored procedure is typically only EXECUTE privilege. This works fine from MySQL workbench or command line.
Upon running the .NET program this does return the following exception:
System.Data.SqlTypes.SqlNullValueException: 'Data is Null. This method or property cannot be called on Null values.'
To make it easy, I have create a very small demo program to demonstrate the issue.
Setup of the database:
CREATE DATABASE Spike;
CREATE PROCEDURE TestAccess()
BEGIN
END;
CREATE USER Spike#localhost IDENTIFIED WITH mysql_native_password BY 'sample';
GRANT EXECUTE ON PROCEDURE `TestAccess` TO Spike#localhost;
Setup program code:
static void Main(string[] args)
{
using (MySqlConnection conn = new MySqlConnection("Server=localhost;Database=Spike;uid=Spike;pwd=sample"))
{
conn.Open();
Console.WriteLine("Connection open");
MySqlCommand cmd = new MySqlCommand();
cmd.Connection = conn;
cmd.CommandText = "TestAccess";
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.ExecuteNonQuery();
Console.WriteLine("Query executed");
}
Console.ReadKey();
}
The crash happens at the line cmd.ExecuteNonQuery();
The stack from the crash is interesting, since it seems to indicate that the information_schema is queried. When logging all statements I can see that the last statement before the exception is:
SELECT * FROM information_schema.routines WHERE 1=1 AND routine_schema LIKE 'Spike' AND routine_name LIKE 'TestAccess'
I cannot grant different rights on information_schema, but I could give more rights on the stored procedure to make more information visible in the routines table, this feels wrong however. Simple tests with granting CREATE and ALTER access also did not work.
Is there something else I can do, without granting too much privileges?
This appears to be a bug in Connector/NET, similar to bug 75301 but a little different. When it's trying to determine parameter metadata for the procedure, it first creates a MySqlSchemaCollection named Procedures with all metadata about the procedure. (This is the SELECT * FROM information_schema.routines WHERE 1=1 AND routine_schema LIKE 'Spike' AND routine_name LIKE 'TestAccess' query you see in your log.)
The Spike user account doesn't have permission to read the ROUTINE_DEFINITION column, so it is NULL. Connector/NET expects this field to be non-NULL and throws a SqlNullValueException exception trying to read it.
There are two workarounds:
1) The first, which you've discovered, is to set CheckParameters=False in your connection string. This will disable retrieval of stored procedure metadata (avoiding the crash), but may lead to harder-to-debug problems calling other stored procedures if you don't get the order and type of parameters exactly right. (Connector/NET can no longer map them for you using the metadata.)
2) Switch to a different ADO.NET MySQL library that doesn't have this bug: MySqlConnector on NuGet. It's highly compatible with Connector/NET, performs faster, and fixes a lot of known issues.
I found an answer with which I am quite pleased. It is changing the connection string by adding CheckParameters=false:
using (MySqlConnection conn = new MySqlConnection("Server=localhost;Database=Spike;uid=Spike;pwd=sample;CheckParameters=false"))
This disables parameter checking, and thereby information_schema queries.
I've got the following
SqlCommand cmd = getSQLCommand();
using (cmd.Connection)
using (cmd)
{
try
{
string dbName = txt_DatabaseName.Text;
var createDatabaseQuery = "exec ('CREATE DATABASE ' + #databaseName)";
var sqlCommand = new SqlCommand(createDatabaseQuery, cmd.Connection);
sqlCommand.Parameters.Add("#databaseName", SqlDbType.Text);
sqlCommand.Parameters["#databaseName"].Value = dbName.ToString();
cmd.Connection.Open();
sqlCommand.ExecuteNonQuery();
}
catch (SqlException ex)
{
Console.WriteLine(ex.ToString());
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "alertMessage", "alert('SQL Error. Record not added.')", true);
}
finally
{
cmd.Connection.Close();
}
}
I'm fully aware that params are not supported in DDL operations, so I've got this really cool thread that I've been using to help me write the contents within the "try".
How to use SqlCommand to CREATE DATABASE with parameterized db name?
That said, I'm still getting an exception error for incorrect syntax near 'Database'. This might be a user error but I've been stuck around this for an hour or so now.
Any thoughts/ improvements?
p.s. All I'm trying to do is to create a database programmatically by using a dynamic value of whatever happens to be in txt_DatabaseName.Text (and yes I will try to error handle this in case there's white spaces entered or any chars that are not supported in SQL.
p.p.s Any articles that I can have a look at against sql injection attacks or any suggestions around constructing the method I have to prevent it? This is a simple exercise that I'm doing on my local machine, not public facing but still would like to get ahead of the game if possible.
You don't need the exec part at all. Again you are getting error after removing exec cause you are wrapping your query in single quote 'CREATE DATABASE ' which is getting considered as string literal. It should just be
var createDatabaseQuery = string.Format("CREATE DATABASE {0}",DBnamevariable);
var sqlCommand = new SqlCommand(createDatabaseQuery, cmd.Connection);
Take a look with the sql profiler to see what is being fired against the database. If it is not working try to execute the query in Management studio to see it that is working. It's probably some kind of special character that is not allowed.
I'm trying to execute a query against an Oracle DB using ODBC in .NET and am getting the following error:
ORA-00933: SQL command not properly ended
However, the SQL statement is definitely correct, and I can execute it successfully from Oracle SQL Developer. The query itself looks like this:
SELECT * FROM TABLE(SCHEMA.PKG.SPNAME('PARAMS'));
Another simple query works fine:
SELECT COUNT(*) FROM SCHEMA.MYTABLE
It looks like something with the former, where it's using a package in the query and causing something to break. The error indicates that it's not properly ended, but it has a semi-colon and correct braces, so it seems something else is going on.
If I remove the trailing semi-colon, I get an error with no message.
My C# code is basic and looks like this:
using (var connection = new OdbcConnection(connectionString))
{
using (var command = connection.CreateCommand())
{
command.CommandText = commandText;
connection.Open();
var result = command.ExecuteScalar();
connection.Close();
Console.WriteLine(result);
}
}
When using the Oracle library for .NET, it works when I remove the trailing semi-colon. If I keep that in place, the same error about the SQL command not being properly ended comes up.
It seems like this query should work with ODBC. Is there anything I need to differently to get it working, or is using the Oracle Managed Data Provider the only way?
From my experience, I have noticed several instances where a semicolon will break the query, such as JasperSoft Studio and the cx_Oracle Python module. I know very little about ODBC vs OracleDataClient, but I would imagine this is a similar situation.
I would not use ODBC I would actually do something like this using the OracleDataClient
var strSQL = "SELECT * FROM TABLE(SCHEMA.PKG.SPNAME('PARAMS'));";
using (OracleConnection connStr = new OracleConnection(connectionString))
{
using (OracleCommand cmd = new OracleCommand(strSQL, connStr))
{
cmd.CommandType = CommandType.Text;
cmd.Connection.Open();
cmd.ExecuteScalar(); //change the ExecuteScalar to fit the proper call
}
}
When I execute a simple select query in SQL Developer against a newly added table or an older table with newly added data, I receive results. But if I run the exact same query in .NET/C# using the most recent Oracle Data Access Client under .NET 4.0, I receive zero results.
I have verified the connection string is correct, and that I am connecting to the same DB, and I have tested using simple "select * from table" queries. Using the same exact .NET code querying against older data...it works just fine. I can only conclude that this is a bug of some sort, or maybe someone who is an Oracle expert knows how this can occur. I know DBs are complex machines and therefore I am hoping there is some logical explanation as to how this can occur...and how I can fix it.
I am an Oracle newbie, but I am a veteran programmer and problem solver. This one really has me stumped.
This is my first SO question, so please be gentle...thanks!
Here is my sample code that returns error saying "...table does not exist...". But table DOES exist and the query works fine in SQL DEV.
String prod_connstr = "Data Source=(DESCRIPTION = (ADDRESS = (PROTOCOL = TCP) (HOST = 10.0.0.17) (PORT = 2621)) " +
"(CONNECT_DATA = (SERVER = DEDICATED) (SERVICE_NAME = XXXXX)));User Id=XXXXX;Password=XXXXX";
String sqlStr = "select * from z_test";
OracleConnection conn = new OracleConnection(prod_connstr);
try
{
conn.Open();
OracleCommand cmd = new OracleCommand(sqlStr, conn);
OracleDataReader dr = cmd.ExecuteReader();
MessageBox.Show(dr.HasRows.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error");
}
finally
{
conn.Dispose();
}
Every time I have seen "...table does not exist..." where you know it does, it means the user you are connecting as (in the connection string) does not have select granted to it. Now if you are connecting with SQL developer and you connection string with the same schema, you have me stumped.
edit: as Oğuz Sezer pointed out if your db doesn't have public synonyms for the tables you will need to use Schema.table (forgot about that)
Right, I have been tasked with developing a new application in MVC3 that unfortunately has to integrate very slightly with a classic asp web site. This won't be forever as the old site will get an update at some point, but not yet. In the mean time however the new MVC3 application will need a little bit of access to the database for the old site, which is a old MS Access .mdb whereas the new app will be using sql server 2008.
I would greatly appreciate it if someone could give me some examples of how to connect to the access db, aswell as how to execute sql queries (i am fine writing the sql, just got no idea how to execute against the database from my mvc3 app).
thanks in advance
EDIT: I've not got much experience with the old site, but it appears to use the JET adaptor if that helps! ;-)
Your question requires an answer too extensive to be given in detail
I will give you a check list of things and class to research
Define the connection string used to reach your database [see
here]
Create and open the OleDbConnection
Define your OleDbCommand and the command text to be executed
Create and use an OleDbDataReader to read your data line by line
Create and use an OleDbDataAdapter to read your data and load a
DataSet or DataTable
Now don't forget to close your connection and use parametrized query
string connectionString = Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\mydatabase.mdb;Jet OLEDB:Database Password=MyDbPassword;
public void InsertRow(string connectionString, string insertSQL)
{
using (OleDbConnection connection = new OleDbConnection(connectionString))
{
// The insertSQL string contains a SQL statement that
// inserts a new row in the source table.
OleDbCommand command = new OleDbCommand(insertSQL);
// Set the Connection to the new OleDbConnection.
command.Connection = connection;
// Open the connection and execute the insert command.
try
{
connection.Open();
command.ExecuteNonQuery();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
// The connection is automatically closed when the
// code exits the using block.
}
}