I am using System.Data.Common.DbProviderFactories to produce a DbProviderFactory for a dynamically-specified database. One of the supported types is MySQL. What I want is to be able to connect to the MySQL server using Integrated Security. I am setting the proper key-value for the connection string below, but when I do not provide a Username and Password, I always get a NullReferenceException. I am using MySQL 6.9.8.0.
If I provide valid credentials in the two connection string values that you will see commented out, no exception is thrown. Although at that point I suspect I am no longer really using Integrated Security. I have tried setting them to both an empty string and to null, but the exception is still thrown either way.
The "my.ini" file includes this already:
# Enable Windows Authentication
plugin-load=authentication_windows.dll
var factory = DbProviderFactories.GetFactory("MySql.Data.MySqlClient");
var conn = factory.CreateConnection();
var cmd = conn.CreateCommand();
var csb = new DbConnectionStringBuilder();
//csb.Add("UserID", "root");
//csb.Add("Password", "root");
csb.Add("Server", _serverName);
csb.Add("Database", _dbName);
csb.Add("Connection Timeout", userVars.DatabaseTimeout);
csb.Add("Default Command Timeout", _commandTimeout);
csb.Add("Ssl Mode", "None");
csb.Add("Integrated Security", true);
csb.Add("Persist Security Info", false);
csb.Add("Pooling", true);
csb.Add("Maximum Pool Size", 200);
csb.Add("Minimum Pool Size", 0);
csb.Add("Sql Server Mode", true);
csb.Add("Ignore Prepare", false);
conn.ConnectionString = csb.ConnectionString;
conn.Open(); //<--- exception is thrown internally, here
Executing this code as-is produces a NullReferenceException when Open() is called. As I am stepping in code, this exception pops 4 times on the Open() line, and then steps (just once) into my enclosing try-catch handler as the NRE.
Object reference not set to an instance of an object
server=localhost;database=information_schema;connectiontimeout=60;defaultcommandtimeout=60;sslmode=None;Integrated
Security=True;persistsecurityinfo=False;pooling=True;maxpoolsize=200;minpoolsize=0;sqlservermode=True;ignoreprepare=False
Stack trace:
at
MySql.Data.MySqlClient.Authentication.MySqlNativePasswordPlugin.MoreData(Byte[]
data) at
MySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin.AuthenticationChange()
at
MySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin.HandleAuthChange(MySqlPacket
packet) at
MySql.Data.MySqlClient.Authentication.MySqlAuthenticationPlugin.Authenticate(Boolean
reset) at MySql.Data.MySqlClient.NativeDriver.Authenticate(String
authMethod, Boolean reset) at
MySql.Data.MySqlClient.NativeDriver.Open() at
MySql.Data.MySqlClient.Driver.Open() at
MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder
settings) at
MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection() at
MySql.Data.MySqlClient.MySqlPool.GetPooledConnection() at
MySql.Data.MySqlClient.MySqlPool.TryToGetDriver() at
MySql.Data.MySqlClient.MySqlPool.GetConnection() at
MySql.Data.MySqlClient.MySqlConnection.Open() at AllMax.Sql.Init()
I have also tried directly using the MySql.Data.MySqlClient version of this code, but the exception is still thrown when no User/Pass is provided. What am I missing here?
Related
When calling the Open() method on a SqlConnection instance that got passed an incomplete connection string, the method does not throw an exception.
I have created the following example to showcase my problem.
var success = true;
var connectionStrings = new[]
{
"Integrated Security=SSPI;",
"Initial Catalog=awdemo;Integrated Security=SSPI;",
"Data Source=.\\sql2016;Initial Catalog=awdemo;Integrated Security=SSPI;"
};
foreach (var connectionString in connectionStrings)
{
var conn = new SqlConnection(connectionString);
try
{
conn.Open();
}
catch (Exception)
{
success = false;
}
finally
{
conn.Close();
Console.WriteLine($"{connectionString} - Success = {success}");
}
}
Result:
Integrated Security=SSPI; - Success = True
Initial Catalog=awdemo;Integrated Security=SSPI; - Success = True
Data Source=.\sql2016;Initial Catalog=awdemo;Integrated Security=SSPI; - Success = True
I would expect conn.Open() to throw an exception for the first two connection strings, since both of them are incomplete and not valid.
Why is there no exception thrown?
EDIT: as pointed out by Steve in the comments an exception is not thrown because the component connects to my default instance of SQL Server when not providing the server information.
Is there a way to force the SqlConnection component to throw an error on incomplete connection strings? In the application it is possible and allowed to create incomplete connection strings.
There's no practical way to fully validate this. You could have a connection string that has all of the components you expect, including a valid server and database name, but it's the wrong server or wrong database.
So if the expectation is that the class should fail on conn.Open() if the connection string is incorrect (not invalid, but incorrect), you can't completely achieve that.
Does it matter? Imagine a few scenarios, all of which include incorrect connection strings:
The connection string is "blarg!" and so attempting to open the connection throws an exception.
The connection string doesn't contain a server or database name. You can open the connection but when you try to execute some command it fails.
The connection string contains a server and database name, but it's the wrong server or database. It fails for the same reason as 2.
In each of the scenarios, what's the first thing you're going to do? You're going to look at the exception. Regardless of which line throws it, you're going to quickly deduce that you have the wrong connection string.
So a "validation" which can't actually validate the connection string before you open it is just going to add work. If the connection string is wrong, that truly is an "exceptional" condition so it's probably better to just let the code throw an exception where it does. You'll find the problem quickly.
All of that aside, suppose you just really want to be sure that your connection contains a server name and a database name before you try to open it. You could write an extension method like this:
// Maybe give it a better name.
public static void ValidateThatConnectionHasDataSourceAndDatabase(this SqlConnection connection)
{
if (string.IsNullOrEmpty(connection.DataSource))
throw new Exception("The connection has no datasource");
if (string.IsNullOrEmpty(connection.Database))
throw new Exception("The connection has no database");
}
After you create the connection and before you open it, call conn.ValidateThatConnectionHasDataSourceAndDatabase();
Summary:
I'm getting a 'Unable to connect to any of the specified MySQL hosts, previously working code' error when trying to connect to a MySQL database through an ASP.NET web application. Full error is below.
The odd thing is that I developed the application in just a temporary new website project and everything works fine there. However, when I work it into the offline version of the website I'm trying to implement it in, this error crops up. Interestingly, I'm actually using a connection string that is already set up and operating correctly within the website. So I'm confused as to why my code operates elsewhere, and the connection string operated elsewhere, but when I try to use them together, I get the 'Unable to connect' error.
What I've tried:
The first thing was obviously to check that my connection string was formatted properly. I did double check this, but as I said the connection string already was (and still does) work with other pages on the site.
I also saw a number of posts regarding this error that suggested I include the tag in the web.config file. This however did not fix the issue for me.
I also verified that my MySQL database is up and operational. As stated, I can get the connection string I'm using to work with other aspects of the page.
Code Snippets:
Full error:
MySql.Data.MySqlClient.MySqlException: Unable to connect to any of the specified MySQL hosts. ---> System.Security.SecurityException: Request for the permission of type 'System.Net.SocketPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessPermission.Demand()
at System.Net.Sockets.Socket.CheckCacheRemote(EndPoint& remoteEP, Boolean isOverwrite)
at System.Net.Sockets.Socket.BeginConnectEx(EndPoint remoteEP, Boolean flowContext, AsyncCallback callback, Object state)
at System.Net.Sockets.Socket.BeginConnect(EndPoint remoteEP, AsyncCallback callback, Object state)
at MySql.Data.Common.StreamCreator.CreateSocketStream(IPAddress ip, Boolean unix) at MySql.Data.Common.StreamCreator.GetStream(UInt32 timeout)
at MySql.Data.MySqlClient.NativeDriver.Open()
The action that failed was: Demand
The type of the first permission that failed was: System.Net.SocketPermission
The first permission that failed was:
The demand was for:
The granted set of the failing assembly was:
The assembly or AppDomain that failed was: MySql.Data, Version=6.2.4.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d
The method that caused the failure was: System.IO.Stream CreateSocketStream(System.Net.IPAddress, Boolean)
The Zone of the assembly that failed was: Intranet The Url of the assembly that failed was: file://PROAPPSRV/inetpub/wwwroot/MyChiller/bin/MySql.Data.DLL -
-- End of inner exception stack trace ---
at MySql.Data.MySqlClient.NativeDriver.Open() at MySql.Data.MySqlClient.Driver.Open() at MySql.Data.MySqlClient.Driver.Create(MySqlConnectionStringBuilder settings) at MySql.Data.MySqlClient.MySqlPool.CreateNewPooledConnection()
at MySql.Data.MySqlClient.MySqlPool.GetPooledConnection() at MySql.Data.MySqlClient.MySqlPool.TryToGetDriver()
at MySql.Data.MySqlClient.MySqlPool.GetConnection()
at MySql.Data.MySqlClient.MySqlConnection.Open()
at TCCVC_Login.ValidateUser(Object sender, EventArgs e)
C# MySQL connector:
using (MySqlConnection conn = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["newrst110ConnectionString"].ConnectionString))
{
using (MySqlCommand cmd = conn.CreateCommand())
{
try
{
cmd.Connection = conn;
conn.Open();
cmd.CommandText = #"SELECT custpass AS hash, (lastlogin IS NOT NULL) AS firstLogin FROM rts110.mychiller_users
WHERE custusername = #user";
cmd.Parameters.AddWithValue("#user", Login1.UserName);
MySqlDataReader reader = cmd.ExecuteReader();
DataTable returnTable = new DataTable();
returnTable.Load(reader);
reader.Close();
// UPDATE LAST LOGIN DATE
cmd.CommandText = #"UPDATE mychiller_users
SET lastLogin = CURDATE()
WHERE custusername = #userName";
cmd.Parameters.AddWithValue("#userName", Login1.UserName);
cmd.ExecuteNonQuery();
cmd.Dispose();
// . . .
// Additional code down here that handles the return and closes the connection.
Connection String:
<add name="newrst110ConnectionString" connectionString="Datasource=70.103.118.100;Database=rts110;uid=####;pwd=####;" providerName="MySql.Data.MySqlClient"/>
Does anyone have an idea why I'm running into this error when the individual components all see to operate correctly?
Thank you in advance for your help.
UPDATE
I've been tinkering around more with this to see if I can narrow the problem down any. I've noticed when I make a test page and just create the very base connector below, I get an application security error, also below.
Simple Connector
DataTable returnTable = new DataTable();
using (var conn = new MySqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["workorderConnectionString"].ConnectionString))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
try
{
cmd.CommandText = #"SELECT * FROM workorder.jobnumber";
MySqlDataReader reader = cmd.ExecuteReader();
returnTable.Load(reader);
reader.Close();
cmd.Dispose();
}
catch (Exception ex)
{
lbltest.Text = ex.ToString();
}
finally
{
conn.Close();
}
}
}
Application Error:
Server Error in '/' Application.
Security Exception
Description: The application attempted to perform an operation not allowed by the security policy. To grant this application the required permission please contact your system administrator or change the application's trust level in the configuration file.
Exception Details: System.Security.SecurityException: Request for the permission of type 'System.Net.SocketPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[SecurityException: Request for the permission of type 'System.Net.SocketPermission, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' failed.]
System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet) +0
System.Security.CodeAccessPermission.Demand() +54
System.Net.Sockets.Socket.CheckCacheRemote(EndPoint& remoteEP, Boolean isOverwrite) +270
System.Net.Sockets.Socket.BeginConnectEx(EndPoint remoteEP, Boolean flowContext, AsyncCallback callback, Object state) +175
System.Net.Sockets.Socket.BeginConnect(EndPoint remoteEP, AsyncCallback callback, Object state) +179
MySql.Data.Common.StreamCreator.CreateSocketStream(IPAddress ip, Boolean unix) +239
MySql.Data.Common.StreamCreator.GetStream(UInt32 timeout) +650
MySql.Data.MySqlClient.NativeDriver.Open() +366
Based on my google searched this again points back to the tag in Web.Config file, which I already have included in there. Perhaps I'm including this incorrectly?
I'm wondering if maybe it might also be related to the two Web.config files I have (One in a subfolder with member pages, to restrict access without validated session). I tried adding the in both and saw no difference.
Could you attach a version of your connectionstring? It seems that there might be a misconfiguration on your config file.
After further research on the application error I was getting with the simplified connection string I stumbled upon the following:
The application attempted to perform an operation not allowed by the security policy
After looking at the answer to that question, I moved my solution to my local drive, because I was running it from a server folder. Doing so solved the issue and everything works perfectly now.
I am using Renci.SshNet.Sftp to connect to SFTP. I am getting the following error when I try to call sftpClientObject.Connect(). Please find below the error. It was working fine couple of days ago. Checked the authentication details and it is perfect.
var _sftpClient = new SftpClient(_hostName, _userName, _password);
using (_sftpClient)
{
_sftpClient.Connect();
// Other code to follow
}
Error:
Value cannot be null.
Parameter name: At least one element in the specified array was null.
Exception stacktrace:
at System.Threading.WaitHandle.WaitAny(WaitHandle[] waitHandles, Int32 millisecondsTimeout, Boolean exitContext)
at System.Threading.WaitHandle.WaitAny(WaitHandle[] waitHandles, TimeSpan timeout, Boolean exitContext)
at System.Threading.WaitHandle.WaitAny(WaitHandle[] waitHandles, TimeSpan timeout)
at Renci.SshNet.Session.WaitHandle(WaitHandle waitHandle)
at Renci.SshNet.PasswordAuthenticationMethod.Authenticate(Session session)
at Renci.SshNet.ConnectionInfo.Authenticate(Session session)
at Renci.SshNet.Session.Connect()
at Renci.SshNet.BaseClient.Connect()
at SftpPoller.FileTransferClient.ProcessFilesInSftp(TextWriter log) in
But when I use the following code, it worked:
var methods = new AuthenticationMethod[1];
methods[0] = new PasswordAuthenticationMethod(_userName, _password);
var con = new ConnectionInfo(_hostName, _userName, methods) {Timeout = new TimeSpan(0, 0, 0, 60)};
_sftpClient = new SftpClient(con);
Can anyone help me how to solve this issue?
Thanks
It seems that the only imaginable scenario, when the PasswordAuthenticationMethod.Authenticate can pass an uninitialized wait handle to WaitHandle.WaitAny is when the session is closed while the authentication is ongoing.
If the session is closed due to a timeout, setting a higher timeout can resolve the problem, as you have found yourself.
A simpler code to set the timeout is:
var _sftpClient = new SftpClient(_hostName, _userName, _password);
_sftpClient.ConnectionInfo.Timeout = TimeSpan.FromSeconds(60);
You seem to be using an old version of SSH.NET (probably the version 2013.4.7 available in NuGet). As the relevant part of the code was refactored in later versions, upgrading might solve this problem too. You should do it anyway as the NuGet SSH.NET package is really old.
I have a service running, that is connected to a few clients. It has been up and running for weeks and this function is called many times every minute, I have a few catches in the different function, but this exception made it all the way to crash. I never seen the issue before. Whan can make this occure?
Stack:
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AccessViolationException
Stack:
at System.Data.OleDb.OleDbServicesWrapper.GetDataSource(System.Data.OleDb.OleDbConnectionString, System.Data.OleDb.DataSourceWrapper ByRef)
at System.Data.OleDb.OleDbConnectionInternal..ctor(System.Data.OleDb.OleDbConnectionString, System.Data.OleDb.OleDbConnection)
at System.Data.OleDb.OleDbConnectionFactory.CreateConnection(System.Data.Common.DbConnectionOptions, System.Object, System.Data.ProviderBase.DbConnectionPool, System.Data.Common.DbConnection)
at System.Data.ProviderBase.DbConnectionFactory.CreateNonPooledConnection(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionPoolGroup)
at System.Data.ProviderBase.DbConnectionFactory.GetConnection(System.Data.Common.DbConnection)
at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(System.Data.Common.DbConnection, System.Data.ProviderBase.DbConnectionFactory)
at System.Data.OleDb.OleDbConnection.Open()
at EServer.Database.DBManager.DoesObjectExsist(System.String)
at EServer.Database.DBManager.setObjectOnline(System.String, Boolean, System.String, System.String)
at EServer.Network.SocketListener.handleToDo()
at EServer.Network.Token.ProcessData(System.Net.Sockets.SocketAsyncEventArgs)
at EServer.Network.SocketListener.ProcessReceive(System.Net.Sockets.SocketAsyncEventArgs)
at EServer.Network.SocketListener.OnIOCompleted(System.Object, System.Net.Sockets.SocketAsyncEventArgs)
at System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(System.Net.Sockets.SocketAsyncEventArgs)
at System.Net.Sockets.SocketAsyncEventArgs.ExecutionCallback(System.Object)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Net.Sockets.SocketAsyncEventArgs.FinishOperationSuccess(System.Net.Sockets.SocketError, Int32, System.Net.Sockets.SocketFlags)
at System.Net.Sockets.SocketAsyncEventArgs.CompletionPortCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32, UInt32, System.Threading.NativeOverlapped*)
Code:
public bool DoesObjectExsist(String ID)
{
try
{
String connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + dbPath + "'";
string mySelectQuery = "SELECT * FROM Object WHERE ID = \"" + ID + "\"";
OleDbConnection myConnection = new OleDbConnection(connectionString);
OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
myConnection.Open();
OleDbDataReader myReader = myCommand.ExecuteReader();
try
{
while (myReader.Read())
{
return true;
}
}
finally
{
myReader.Close();
myConnection.Close();
}
return false;
}
catch (Exception e)
{
return false;
}
}
EF Core Update
The followings sections are a bit dated and are about EF6 and .NET Framework 4.x.
Nowadays, if you are using .NET (Core), use the EntityFrameworkCore.Jet EF Core provider. Use the latest prerelease, that references the 5.0.0 OLE DB libraries, that contain some major bugfixes.
AccessViolationException
This issue is a bug within the ACE 2010 engine. A workaround can be found in the original bug report on microsoft connect (see FranzT):
In my Applicationn I have the same problem. MS Access DB is a backend for this app(C#, .NET 2.0, VS 2005).
When in connection string as provider OLEDB.4.0 is used, it works fine. When the data access provider is ACE.OLEDB.12 I get an Exception if OpenFileDialog is used.
In connection string is possibel to set many parameters, OLE DB Services too.
When OLE DB Services=default (-13, pooling disabled) I get the
Exception. When OLE DB Services=EnableAll (-1, pooling enabled) it
works fine.
If I set OLE DB Services=-2 (EnableAll without pooling) I get the Exception.
My workaround is: set the OLE DB services=-1(EnableAll).
The workaround is based on the research of a microsoft forum user by the name of Elmar Boye, who goes into detail about the nature of the issue (though in German):
https://social.msdn.microsoft.com/Forums/de-DE/500055e5-6189-418c-b119-fdc0367e0969/accessviolationexception-bei-openfiledialog-nach-ffnen-und-schlieen-einer-2-form?forum=dotnetframeworkde
Basically, the ACE 2010 engine is accessing memory it doesn't own. And if the database is already unloaded at the time the engine accesses the memory, the exception is thrown. To workaround the issue, connection pooling can be used, since it keeps the database connection open and therefore the database in memory. It can be enabled using different combinations of OLE DB Services flags.
A good flag value is the original default, which enables all services (though this default seems to be overwritten by a registry key, which is why it makes sense to manually provide the value in the connection string):
OLE DB Services=-1
Though the bug report addresses a problem within the open file dialog, the root cause is the same as for other AccessViolationException cases using the ACE 2010 provider for Access.
There is also a link to a Hotfix that supposedly fixes the issue.
By the way, this exception does not occur using the Microsoft.Jet.OLEDB.4.0 provider.
JetEntityFrameworkProvider
For those like me who are using the JetEntityFrameworkProvider by bubibubi make sure that you are using the workaround in your production connection string, but not in your connection string you use for applying database migrations, because it will throw a OleDbException E_UNEXPECTED(0x8000FFFF) on the second Update-Database command while trying to open the database and will lockup the Package Manager Console on every command execution thereafter (until you restart Visual Studio).
Access and multi user scenarios
Access is build for simultaneous multi user access over a network share. So this is a scenario that is explicitly supported.
#Hans Passant and #user2905764
Why dont you make it more sumpler by using this. If would greate if you wrap connection, command and reader objects inside a using statement block. See usage of using.
Update
Sorry , I saw this couple of minutes ago that, you are using Access db for Services, which is, I think completely insane. Since services are consumed by various clients at a time so it might lead to inconsistency. So, as Hans Passant suggested in his comment, kindly go for Sql Server Express or MySql like Server-Oriented database for such scenarios.
public bool DoesObjectExsist(String ID)
{
bool result=false;
try
{
String connectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source='" + dbPath + "'";
string mySelectQuery = "SELECT Count(*) FROM Object WHERE ID = ?";
OleDbConnection myConnection = new OleDbConnection(connectionString);
OleDbCommand myCommand = new OleDbCommand(mySelectQuery, myConnection);
command.Parameters.AddWithValue("#id",ID);
myConnection.Open();
OleDbDataReader myReader = myCommand.ExecuteReader();
try
{
if(reader.HasRows)
result=true;
}
finally
{
myReader.Close();
myConnection.Close();
}
}
catch (Exception e)
{
//log exception
}
return result;
}
I'm trying to connect a C# application (using Visual C# 2008 Express Edition) to a remote MySQL server. I have the drivers for this, but when I followed the tutorials (including adding the pooling and connection reset properties), I get an error that: Object reference not set to an instance of an object. I've included the two lines of code that should be making a connection. The error is thrown on the second line.
MySqlConnection connect = new MySqlConnection("database=d*******;Data Source=mysql.netfirms.com;user id=*******;pwd=*****;pooling=false;connection reset=false");
connect.Open();
I'd try setting the connection string outside of the constructor to help narrow down the issue:
MySqlConnection connect = new MySqlConnection();
//Do you get the null exception in this next line?
connect.ConnectionString = "your conn string here";
connect.Open(); //-> If you get the exception here then the problem is with the connection string and not the MySqlConnection constructor.
If you do get the exception in the connect.ConnectionString = ... line, then the problem is with the driver and sounds like you need to reinstall it.
I would also try a simpler connection string, without the pooling and reset keys.
Can you post more code? The exception line is probably a bit off due to compiler optimization or related. Constructors must return an object or throw an exception. It is impossible to say
MyType item = new MyType();
Debug.Fail(item == null); // will never fail.
The null reference is probably on the line just above your instantiation.