I'm updating an old project, moving its data source from Sybase to SQL Server. The data structures are identical (they're both copies of a commercial database - the Sybase version has been discontinued).
Because it's pretty old, it uses ODBC to connect. The connection strings originally specified a DSN. I've managed to connect to the SQL Server using both a raw connection string and a replacement DSN.
It executes code against the database by pulling command text from a config file and adding named parameters, like so:
var args = new Dictionary<string, object>()
{
{ "#myFirstParam", "myFirstValue" },
{ "#mySecondParam", "mySecondValue" }
}
IDbCommand cmd = Connection.CreateCommand();
cmd.CommandType = CommandType.Text;
cmd.CommandTimeout = Command.Timeout;
cmd.CreateParameters(Command.Parameters, args);
cmd.CommandText = [fetched from config]
IDataReader reader = null;
reader = cmd.ExecuteReader();
This all used to work fine with Sybase.
However, when I run it against SQL, when the reader executes I get the following error:
ERROR [42000] [Microsoft][ODBC Driver 17 for SQL Server][SQL Server]Must declare the scalar variable "#myFirstVariable".
I get this error whether I specify the connection as a DSN or a raw string. Stepping through the code, the parameter is certainly declared and has a valid value.
Reading up around this, it appears that this behaviour is to be expected. The Microsoft Documentation on ODBC connection says you can only use named parameters if you're calling a stored procedure, which I am not. Apparently the correct method is to put "?" characters in the command text and ODBC will insert the parameters by index.
If this is correct, I have no idea how this code ever worked with Sybase. I have another project which uses the same code for data loading, specifying named parameters and passing them into SQL command specified in config, but it's pointing at a different SQL Server database.
I presume this may be something to do with the configuration of the database, but I'm pretty lost on what to try from here. Any suggestions would be greatly appreciated.
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 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;
}
OleDbCommand oleDbCmd = new OleDbCommand();
OleDbConnection bookConn = Sqlhelper.Conncect_Mdb();
oleDbCmd.Connection = bookConn;
oleDbCmd.CommandText = "ALTER TABLE doc_comp ADD COLUMN versioncode NUMBER DEFAULT 0";
oleDbCmd.ExecuteNonQuery();
bookConn.Close();
Here is my code for alter table in ms access,it throws error Syntax error in table-level validation expression.This code works fine for without adding 'DEFAULT 0'. I am using MS ACCESS 2007.Tried with this but I cant set using tools.
Your code works for me if I use the following connect string:
static public OleDbConnection Conncect_Mdb()
{
const string oledb = #"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=scratch.accdb";
var conn = new OleDbConnection(oledb);
conn.Open();
return conn;
}
There are older drivers, specially the ones that run over ODBC that require you to indicate which sql support you need in the driver. An example of such seting in an Odbc connectionstring is ExtendedAnsiSQL=1.
If your setup doesn't have the Microsoft Access Database Engine 2010, which also support Access 2007, you can download and install the redistributable from the Microsoft Download.
This answer does not pertain to the specific question, but it does answer EXACTLY for the error message posted in the TITLE....
Syntax error in table-level validation expression in MS ACCESS
I received this exact error and the fix was to remove a semi colon from the end of the query statement.
I am using the OP's query to present the solution...
oleDbCmd.CommandText = "ALTER TABLE doc_comp ADD COLUMN versioncode NUMBER DEFAULT 0**;**";
Should be,
oleDbCmd.CommandText = "ALTER TABLE doc_comp ADD COLUMN versioncode NUMBER DEFAULT 0";
Remove the semi colon surrounded by asterisks from the query statement. This resolved this EXACT error for me.
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.
}
}
I have a very odd issue. When I execute a specific database stored procedure from C# using SqlCommand.ExecuteNonQuery, my stored procedure is never executed.
Furthermore, SQL Profiler does not register the command at all. I do not receive a command timeout, and no exeception is thrown.
The weirdest thing is that this code has worked fine over 1,200,000 times, but for this one particular file I am inserting into the database, it just hangs forever.
When I kill the application, I receive this error in the event log of the database server: "A fatal error occurued while reading the input stream from the network. The session will be terminated (input error: 64, output error: 0). Which makes me think that the database server is receiving the command, though SQL Profiler says otherwise.
I know that the appropiate permissions are set, and that the connection string is right as this piece of code and stored procedure works fine with other files.
Below is the code that calls the stored procedure, it may be important to note that the file I am trying to insert is 33.5MB, but I have added more than 10,000 files larger than 500MB, so I do not think the size is the issue:
using (SqlConnection sqlconn = new SqlConnection(ConfigurationManager.ConnectionStrings["TheDatabase"].ConnectionString))
using (SqlCommand command = sqlconn.CreateCommand())
{
command.CommandText = "Add_File";
command.CommandType = CommandType.StoredProcedure;
command.CommandTimeout = 30 //should timeout in 30 seconds, but doesn't...
command.Parameters.AddWithValue("#ID", ID).SqlDbType = SqlDbType.BigInt;
command.Parameters.AddWithValue("#BinaryData", byteArr).SqlDbType = SqlDbType.VarBinary;
command.Parameters.AddWithValue("#FileName", fileName).SqlDbType = SqlDbType.VarChar;
sqlconn.Open();
command.ExecuteNonQuery();
}
There is no firewall between the server making the call and the database server, and the windows firewalls have been disabled to troubleshoot this issue.
I've seen this once before when uploading XML via a stored proc from one workstation only
We changed the network cable (which routed differently in our big building) and it worked.
Bizarre as this sounds, can you somehow re-mount the server or change cables or bypass a switch etc.