Turning on multiple result sets in an ODBC connection to SQL Server - c#

I have an application that originally needed to connect to Sybase (via ODBC), but I've needed to add the ability to connect to SQL Server as well. As ODBC should be able to handle both, I thought I was in a good position.
Unfort, SQL Server will not let me, by default, nest ODBC commands and ODBCDataReaders - it complains the connection is busy (Connection is busy with results for another command).
I know that I had to specify that multiple active result sets (MARS) were allowed in similar circumstances when connecting to SQL Server via a native driver, so I thought it wouldn't be an issue.
The DSN wizard has no entr
y when creating a SystemDSN.
Some people have provided registry hacks to get around this, but this did not work (add a MARS_Connection with a value of Yes to HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\system-dsn-name).
Another suggestion was to create a file-dsn, and add "MARS_Connection=YES" to that. Didn't work.
Finally, a DSN-less connection string. I've tried this one (using MultipleActiveResultSets - same variable as a Sql Server connection would use),
"Driver={SQL Native Client};Server=xxx.xxx.xxx.xxx;Database=someDB;Uid=u;Pwd=p;MultipleActiveResultSets=True;"
and this one:
"Driver={SQL Native Client};Server=192.168.75.33\\ARIA;Database=Aria;Uid=sa;Pwd=service;MARS_Connection=YES;"
I have checked the various connection-string sites - they all suggest what I've already tried.
I should state that I've tried both the SQL Server driver, and the SQL Server native driver...

According to the SNI documentation on Using Multiple Active Result Sets (MARS):
The SQL Server Native Client ODBC
driver supports MARS through additions
to the SQLSetConnectAttr and
SQLGetConnectAttr functions.
SQL_COPT_SS_MARS_ENABLED has been
added to accept either
SQL_MARS_ENABLED_YES or
SQL_MARS_ENABLED_NO, with
SQL_MARS_ENABLED_NO being the default.
In addition, a new connection string
keyword, Mars_Connection, as been
added. It accepts "yes" or "no"
values; "no" is the default.
Make sure your client loads the right drivers, use Mars_Connection=yes, and validate in the app by checking SQL_COPT_SS_MARS_ENABLED on SQLGetConnectAttr.

Related

Informix connection string field descriptions and values to be used

I am writing a test application in .net using c# to connect to IBM's Informix database.
So far what i did is, i installed Informix client sdk v4.10 in my machine. After that i wrote a piece of code referring from here and here. In my code i have a reference to IBM.Data.Informix.dll which is referred from installed path of Informix client sdk's bin folder netf40.
When i run a test application, i am getting below error while trying to opening up an connection,
ERROR [HY000] [Informix .NET provider][Informix]System error occurred
in network function.
i assume this error is due to connection string field not been supplied properly, i referred https://www.connectionstrings.com/informix/ and tried using connection string like informix with ODBC driver and informix .net provider mentioned in above link but no use, i am also having difficulty in understanding from where to get values for each connection string fields like protocol, port, host-name , server-name and service name.
To find values of above fields, i tried looking for SQLHOSTS key in registry entries under HKEY_LOCAL_MACHINE\SOFTWARE\INFORMIX\ unfortunately it wasn't there! and also tried running setnet32.exe from client sdk's bin folder and i could see below screen with only protocol info!.
It would be really helpful if anyone can help me.
This is a very, very difficult question to answer blind. :-)
setnet32.exe will not know the information you are looking for, you need to provide this information to setnet32.exe.
The first question to ask is: is your database running on Unix or Linux? If it is, then by logging in to the database server as user "informix" and running the command
cat $INFORMIXDIR/etc/sqlhosts
If you're on Windows, then login to the Windows server and from a command prompt, run
TYPE %INFORMIXDIR%\etc\sqlhosts
This should give you a file with potentially a bunch of information, you're looking for lines that are not comments and have at least 4 columns. This is my sqlhosts file on a Docker I'm testing:
$ cat $INFORMIXDIR/etc/sqlhosts
############################################################
### DO NOT MODIFY THIS COMMENT SECTION
### HOST NAME = 7edf3045c382
############################################################
informix onsoctcp 7edf3045c382 9088
informix_dr drsoctcp 7edf3045c382 9089
The last two lines are the guts of the file.
Column 1 is the name of the INFORMIXSERVER or an alias (IBM Informix Server in setnet32.exe)
Column 2 is the protocol name (Protocolname in setnet32.exe)
Column 3 is the host name (HostName in setnet32.exe)
Column 4 is the port number or name (Service name in setnet32.exe)
If column 4 is a name and you're on Unix or Linux, then search for the port name in /etc/services on your Unix or Linux server. If you're on Windows, then it will be in %windir%\system32\drivers\etc\services (or similar).
Once you have that, you can then run the command
dbaccess
Choose the Database option, followed by the Select option. This should present you with a list of databases, roughly like:
SELECT DATABASE >>
Select a database with the Arrow Keys, or enter a name, then press Return.
------------------------------------------------ Press CTRL-W for Help --------
backbone#informix wallet#informix
cust#informix
retail#informix
sports#informix
sysadmin#informix
sysha#informix
sysmaster#informix
sysuser#informix
sysutils#informix
In general, databases called "sys" are reserved for Informix administration, and may not be actual databases, although you can query them with SELECTs, you probably won't be able to (and really shouldn't!!) INSERT, UPDATE or DELETE or use DDL.
In my database list above, all the sys* databases are Informix administration "databases". Database names are shown in my example in "databasename#informixservername" format.
You should now have all the information you need to access your database.

Is there a better way to see MySql statements with parameters in C# using Visual Studios debugger?

I have recently been changing some C# programs to add proper parameterizing to some MySQL statements that had originally been written with concatenated strings. Invariably, I've run into some problems with my statements and I can't find a way to directly see the complete MySQL statement with parameters applied other than this workaround that I have where I pass the MySQL command to this:
private string getMySqlStatement(MySqlCommand cmd)
{
string result = cmd.CommandText.ToString();
foreach (MySqlParameter p in cmd.Parameters)
{
string addQuote = (p.Value is string) ? "'" : "";
result = result.Replace(p.ParameterName.ToString(), addQuote + p.Value.ToString() + addQuote);
}
return result;
}
This works, but I was wondering if there was a more proper way to see the full statement with parameters applied. Reading up on this, it looks like the parameters aren't actually applied until it reaches the server - is this correct? In that case, I suppose I can stick to my function above, but I just wanted to know if there was a better way to do it.
Note: I am just using this function for debugging purposes so I can see the MySQL statement.
MySQL supports two protocols for client/server communication: text and binary. In the text protocol, there is no support for command parameters in the protocol itself; they are simulated by the client library. With Connector/NET, the text protocol is always used, unless you set IgnorePrepare=true in the connection string and call MySqlCommand.Prepare() for each command. So it's most likely the case that you are using the text protocol. This is good, because it will be easier to log the actual statements with parameters applied.
There are three ways to view the statements being executed:
Use Connector/NET Logging
Add Logging=true to your connection string and create a TraceListener that listens for the QueryOpened event. This should contain the full SQL statement with parameters interpolated. Instructions on setting this up are here.
Use MySQL Server Logging
Enable the general query log on your server to see all queries that are being executed. This is done with the --general_log=1 --general_log_file=/var/path/to/file server options.
Packet Sniffing
If you're not using SslMode=Required (to encrypt the connection between client and server), then you can use WireShark to capture network traffic between your client and the server. WireShark has MySQL Protocol analysers that will inspect MySQL traffic and identify command packets (that contain SQL queries). This option is ideal if you aren't able to modify your client program nor change server logging settings.

Extremely slow mysql connection establishment only when called from code

I am currently trying to do something that should be simple and straight-forward - connect to a database server, run a query, see if I get anything back and if so send it back to the user. This is the code I'm using to do it:
MySqlDataReader reader = MySqlHeaper.ExecuteReader(connectionString, $"SELECT * FROM table WHERE insertDateTime > '{DateTime.Now.AddSeconds(-1800).ToString("yyyy-MM-ddTHH:mm:ss")}'";
I have also tried this with a MySqlCommand and MySqlConnection object pair, and either way the result is the same - it takes approximately 7100ms to connect to the MySql server. I know that sounds like a problem that should be on ServerFault, but my testing tells me otherwise. When I use the command line MySql client to connect to my database server using exactly the same credentials and run exactly the same query I get my connection established and my data back in nothing flat. I don't know at this stage if it's a server setting or not, but here's what I've tried so far:
Rebooting the server
Restarting the MySQL server
Setting the skip_name_resolve setting to 1 in order to prevent reverse name lookups on connect
Using alternative means of querying the server (mysql command line client and MySQL Workbench)
Opening all AWS IAM permissions on the RDS instance to allow everything from the server
Nothing seems to be making any difference, so I'm at a loss to explain this terrible performance. It's also only happening when I open the connection. Running queries, inserts, what have you is lightning fast. Any suggestions anyone might have would be most helpful.
I would not expect IAM permissions to have any impact on performance. I would expect them to be either successful or not successful.
I would execute some diagnostic protocols to get more information.
1) Try a subsequent query, to see if it is an issue with the stack being initialized. Are subsequent queries faster?
2) Try a query that is just an identity query. Something that doesn't require any sort of IO.
3) Try a query from a different platform (maybe a scripting language like ruby or php)
Once you answer those it should help you narrow it down.
This is most likely caused by Connector/NET executing a slow WMI query to query connection attributes when opening the connection; this is logged as MySQL bug 80030.
As far as I know, this isn't fixed in newer versions of the driver, but you can work around it by switching to MySqlConnector, an OSS MySQL ADO.NET library.

How to Connect Crystal Reports to MySQL directly by C# code without DSN or a DataSet

How can I connect a Crystal Report (VS 2008 basic) to a MySQL DB without using a DSN or a preload DataSet using C#?
I need install the program on several places, so I must change the connection parameters. I don't want to create a DSN on every place, nor do I want to preload a DataSet and pass it to the report engine. I use nhibernate to access the database, so to create and fill the additional DS would take twice the work and additional maintenance later. I think the best option would be to let the crystal reports engine to connect to MySQL server by itself using ODBC.
I managed to create the connection in the report designer (VS2008) using the Database Expert, creating an ODBC(RDO) connection and entering this connection string
"DRIVER={MySQL ODBC 5.1 Driver};SERVER=myserver.mydomain"
and in the "Next" page filling the "User ID", "Password" and "Database" parameters. I didn't fill the "Server" parameter. It worked. As a matter of fact, if you use the former connection string, it doesn't matter what you put on the "Server" parameter, it seems the parameter is unused. On the other hand, if you use "DRIVER={MySQL ODBC 5.1 Driver}" as a connection string and later fill the "Server" parameter with the FQDN of the server, the connection doesn't work.
How can I do that by code? All the examples I've seen till now, use a DSN or the DataSet method. I saw the same question posted but for PostgreSQL and tried to adapt it to mysql, but so far, no success. The first method:
Rp.Load();
Rp.DataSourceConnections[0].SetConnection("DRIVER={MySQL ODBC 5.1 Driver};SERVER=myserver.mydomain", "database", "user", "pass");
Rp.ExportToDisk(ExportFormatType.PortableDocFormat, "report.pdf");
raise an CrystalDecisions.CrystalReports.Engine.LogOnException during ExportToDisk
Message="Logon failed.\nDetails: IM002:[Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified.\rError in File temporal file path.rpt:\nUnable to connect: incorrect log on parameters.
the InnerException is an System.Runtime.InteropServices.COMException with the same message and no InnerException
The "no default driver specified" makes me wonder if the server parameter is unused here too (see above). In that case: How can I specify the connection string?
I haven't tried the second method because it doesn't apply.
Does anybody know the solution?
I think it'll likely be quicker to generate the Dataset via nHibernate, or do a direct ADO.NET query, then trying to solve the issue.

Why does this OdbcConnection throw me a System.InvalidOperationException?

I am building a Winforms C# 2.0 application.
I have successfully been able to connect to my SLQ Server database using the following:
m_connexion = new SqlConnection("server=192.168.xxx.xxx;uid=...;pwd=...;database=...");
Because my company wanted to be able to use any database, I went on to use the Odbc driver and my commands went on like this:
m_connexion = new OdbcConnection("server=192.168.xxx.xxx;uid=...;pwd=...;database=...");
However, this throws out a System.InvalidOperationException. Any idea why?
I'm also trying to use a DSN, but the commend
OdbcConnection connection = new OdbcConnection("DSN=MyDataSourceName"); suggested here but it likewise throws my a System.InvalidOperationException
The connection string needs a Provider= so that the ODBC drivers know which server you're connecting to. In this case Provider=SQLSERVER I believe.
UPDATE: Should have been Provider=SQLOLEDB
I think you need to specify a driver. Look here for details: http://connectionstrings.com/sql-server-2005#21
If you specify a DSN, you have to configure the DSN using the ODBC control panel. It's called "Set up data sources (ODBC)" under Administrative Tools. The panel also has a "test" button, which might tell you more about what's going wrong.
P.S. Being "database independent" is much more work than using ODBC connection, command and datareader. You'd have to make sure your queries run on each target database, which you will not be able to do if you don't have a test server of each. So if I were you, I'd code it up using SqlConnection, since you already got that working.

Categories