I've got an issue where I cannot connect to an on-premises SQL database through an Azure function app once it is published to Azure. However when I run it locally in Visual Studio Code, it works perfectly.
The purpose of the Function is to resize images that are stored in Azure blob storage to a thumbnail and store it in a table field <varbinary(max)>.
Here is the error message I get:
2020-12-15T15:33:52.058 [Information] A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)
2020-12-15T15:33:52.093 [Error] Executed 'BlobTrigger_MQS_Resize' (Failed, Id=346672c6-820c-43f6-b950-d5059e44697e, Duration=19570ms)
Access is denied.
I'm connecting to the SQL database via SQL Login, which works perfectly. Connection String is in local.settings.json:
{
"IsEncrypted": false,
"Values": {
...,
"Connection_SQL_Database_MQS": "Data Source=MyServer;Initial Catalog=MyDB;User ID=MyUser;Password=MyPassword;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
}
}
The code (in C#) which I have simplified a bit to the core of the issue:
public static class BlobTrigger_MQS_Resize
{
[FunctionName("BlobTrigger_MQS_Resize")]
public static async Task Run([BlobTrigger("mqs-media/{name}", Connection = "hqdevstorage_STORAGE")]Stream input, string name, ILogger log)
{
log.LogInformation($"C# Blob trigger function Processed blob\n Name:{name} \n Size: {input.Length} Bytes");
try
{
var connectionString = Environment.GetEnvironmentVariable("Connection_SQL_Database_MQS", EnvironmentVariableTarget.Process);
using (var output = new MemoryStream())
using (Image<Rgba32> image = Image.Load(input))
using (SqlConnection conn = new SqlConnection(connectionString))
{
// Code that resizes images to 'output', this works also when published
image.Resize(...);
image.Save(output, encoder);
//PROBLEM IS HERE: Write resized image to SQL Database
conn.Open();
var query = "UPDATE dbo.MyTable"
+ " SET Blob = #output"
+ " WHERE File_Name = '" + name + "'";
using(SqlCommand cmd = new SqlCommand(query, conn))
{
cmd.Parameters.AddWithValue("#output", output);
var rows = await cmd.ExecuteNonQueryAsync();
log.LogInformation($"{rows} rows were updated");
}
}
}
catch (Exception ex)
{
log.LogInformation(ex.Message);
throw;
}
}
}
Can someone help me with this? I have no clue why it is working locally but not on Azure.
The server was not found or was not accessible.
This is a network connectivity issue, not a permissions issue. The Azure function cannot resolve your SQL Server's hostname into an IP address, and would not be able to connect to that IP address if it could.
Your function would need to access to an on-prem conected VNet or use a Hybrid Connection to reach your on-prem SQL Server.
see
https://learn.microsoft.com/en-us/azure/app-service/app-service-hybrid-connections
and
https://learn.microsoft.com/en-us/azure/azure-functions/functions-create-vnet
Related
My connection string looks like this:
Data Source=sql88;Initial Catalog=Osm;User ID=foouser;Password=foopsw
The code that creates connection string looks like this:
var con = new SqlConnectionStringBuilder();
if (string.IsNullOrEmpty(model.Username) && string.IsNullOrEmpty(model.Password))
con.IntegratedSecurity = true;
else
{
con.UserID = model.Username;
con.Password = model.Password;
}
con.DataSource = model.Host ?? string.Empty;
con.InitialCatalog = model.Database ?? string.Empty;
return con;
My application creates database structure at SQL Server, then inserting data. So sometimes the applcation works approximately 14 hours. The code that executes SQL at SQL Server looks like this:
using (var cmd = con.CreateCommand())
{
cmd.CommandTimeout = int.MaxValue;
cmd.CommandText = sql;
try
{
cmd.ExecuteNonQuery();
}
catch (Exception ex)
{
var test = ex.Message;
throw;
}
}
Sometimes application works well, but sometimes application throws an error:
A network-related or instance-specific error occurred while
establishing a connection to SQL Server. The server was not found or
was not accessible. Verify that the instance name is correct and that
SQL Server is configured to allow remote connections.
provider: TCP Provider, error: 0 - No such host is known.) (Microsoft
SQL Server, Error: 11001)
I've read this page, however, in my view this is not my case because sometimes my application works well.
I am trying to write a program which interacts with my SQL Server database. I am programming in C# on Parallels on my Mac and SQL Server is running via Docker.
But I just can't connect. I am just getting the same error every time I try.
I have already tried to allow the remote access on SQL Server with:
EXEC sp_configure 'remote access', 1 ;
GO
RECONFIGURE ;
GO
but this does not solve my problem.
Here is my C# code:
main Class
Database database;
public Form1()
{
InitializeComponent();
database = new Database("localhost\\MSSQLSERVER", "user1", "topsecret", "master"); // \
}
private void connect_button_Click(object sender, EventArgs e)
{
database.Connect();
}
Database class:
class Database
{
SqlConnectionStringBuilder builder;
SqlConnection connection;
public Database(string source, string userid, string password, string initialcatalog){
this.builder = new SqlConnectionStringBuilder();
this.builder.DataSource = source;
this.builder.UserID = userid;
this.builder.Password = password;
this.builder.InitialCatalog = initialcatalog;
}
public void Connect()
{
try
{
// Connect to SQL
Console.WriteLine("Connecting to SQL Server ... ");
this.connection = new SqlConnection(this.builder.ConnectionString);
connection.Open();
Console.WriteLine("Connected");
}
catch(SqlException sqle)
{
Console.WriteLine(sqle.Message);
}
}
}
And I am always getting this error:
Network-related or instance-specific error when connecting to SQL Server. The server was not found or can not be accessed. Verify that the instance name is correct and that SQL Server allows remote connections. (provider: SQL Network Interfaces, error: 25 - connection string invalid)
The MSSQLSERVER is the instance name of the unnamed, default instance on your machine - you must not use this in the connection string.
Instead, try this line of code:
database = new Database("localhost", "user1", "topsecret", "master");
Just specify no explicit instance name at all - just localhost (or (local), or .) for the current machine - that's all you need!
It was Problem with Parallels, because Paralles can not access to localhost. So i had to define the IP from Parallels in Visual Studio like this:
database = new Database("10.211.55.2", "user1", "topsecret", "Time");
I'm trying to connect my Emulator app to a MySQL Database i created. It works if i access the database using an app/website from the LAPTOP. But it fails to recognize the database if i am accessing it using the EMULATOR, my guess it that it treats the Windows Emulator as an external device. I already added Port 3306 (Default MySQL Port) in the firewall exceptions, freed database privileges, and used the IP Address of the Laptop and Emulator, and still, i get the "Cannot connect to any of the specified MySQL Hosts".
DB Connection Code:
private async void dbConnectAsync()
{
string con = "server=192.168.8.100:3306;database=donation;uid=root;password=;SslMode=none;CharSet=utf8";
MySqlConnectionStringBuilder sb = new MySqlConnectionStringBuilder(con);
using (conn = new MySqlConnection(con))
try
{
conn.Open();
}
catch (Exception err)
{
var dialog2 = new MessageDialog(err.Message);
dialog2.Title = "Connection Error";
dialog2.Commands.Add(new UICommand { Label = "Ok", Id = 0 });
var res = await dialog2.ShowAsync();
}
}
Fixed using host PC's IP Address which is 192.168.8.100 and removed the :3306 fixed the issue.
I tried to connect to the Azure MySQL database using MySQL Workbench and MySQL Shell and it works fine. Now I am trying to connect using following C# code:
var connStringBuilder = new MySqlConnectionStringBuilder
{
Server = "creatur-db.mysql.database.azure.com",
Database = "test",
UserID = "creatur_db_main#creatur-db",
Password = "{my_password}",
SslMode = MySqlSslMode.Preferred,
};
using (MySqlConnection connection = new MySqlConnection(connStringBuilder.ToString()))
{
connection.Open();
connection.Close();
}
Here I replaced {my_password} with password to the database and it gives me an exception inside Open method:
MySql.Data.MySqlClient.MySqlException: 'Authentication to host
'creatur-db.mysql.database.azure.com' for user
'creatur_db_main#creatur-db' using method 'mysql_native_password'
failed with message: The connection string may not be right. Please
visit portal for references.
I also tried different connection strings:
Server=creatur-db.mysql.database.azure.com; Port=3306; Database=test; Uid=creatur_db_main#creatur-db; Pwd={my_password}; SslMode=Preferred
and
Database=test; Data Source=creatur-db.mysql.database.azure.com; User Id=creatur_db_main#creatur-db; Password={my_password}
But none of them worked.
The same exception occurs when I create new connection using Server Explorer in Visual Studio 2013. It seems the error has something to do with .NET Connector. I tried to use different versions of MySQL.Data.dll, .NET Framework and Visual Studio but no luck.
I just created a console application using VS2017 I used
Nuget package MySql.Data and .Net Framework 4.6.1
It works perfectly here What I did.
After Creating the MySQL server I used the CloudShell to connect to the SERVER (not a database).
Using this code:
mysql --host franktest.mysql.database.azure.com --user frank#franktest -p
I got an error
ERROR 9000 (HY000): Client with IP address '40.76.202.47' is not allowed to connect to this MySQL server.
So I add that IP and at the same time my IP from where I'm connected.
So once the IP were saved. I executed the previous command, and this time it worked perfectly. I created a database named: frankdemo using this command:
CREATE DATABASE frankdemo;
Then, back in VisualStudio used this code as my Main method, copied from the documentation.
static void Main(string[] args)
{
var builder = new MySqlConnectionStringBuilder
{
Server = "franktest.mysql.database.azure.com",
Database = "frankdemo",
UserID = "frank#franktest",
Password = "gr3enRay14!",
SslMode = MySqlSslMode.Required,
};
using (var conn = new MySqlConnection(builder.ConnectionString))
{
Console.WriteLine("Opening connection");
conn.Open();
using (var command = conn.CreateCommand())
{
command.CommandText = "DROP TABLE IF EXISTS inventory;";
command.ExecuteNonQuery();
Console.WriteLine("Finished dropping table (if existed)");
command.CommandText = "CREATE TABLE inventory (id serial PRIMARY KEY, name VARCHAR(50), quantity INTEGER);";
command.ExecuteNonQuery();
Console.WriteLine("Finished creating table");
command.CommandText = #"INSERT INTO inventory (name, quantity) VALUES (#name1, #quantity1),
(#name2, #quantity2), (#name3, #quantity3);";
command.Parameters.AddWithValue("#name1", "banana");
command.Parameters.AddWithValue("#quantity1", 150);
command.Parameters.AddWithValue("#name2", "orange");
command.Parameters.AddWithValue("#quantity2", 154);
command.Parameters.AddWithValue("#name3", "apple");
command.Parameters.AddWithValue("#quantity3", 100);
int rowCount = command.ExecuteNonQuery();
Console.WriteLine(String.Format("Number of rows inserted={0}", rowCount));
}
// connection will be closed by the 'using' block
Console.WriteLine("Closing connection");
}
Console.WriteLine("Press RETURN to exit");
Console.ReadLine();
}
Runed it and it works
The documentation I'm referring to is:
Create an Azure Database for MySQL server by using the Azure portal
Azure Database for MySQL: Use .NET (C#) to connect and query data
I have a piece of code that creates an SQL Server Express 2008 in runtime, and then tries to connect to it to execute a database initialization script in Transact-SQL. The code that creates the database is the following:
private void CreateDatabase()
{
using (var connection = new SqlConnection(
"Data Source=.\\sqlexpress;Initial Catalog=master;" +
"Integrated Security=true;User Instance=True;"))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText =
"CREATE DATABASE " + m_databaseFilename +
" ON PRIMARY (NAME=" + m_databaseFilename +
", FILENAME='" + this.m_basePath + m_databaseFilename + ".mdf')";
command.ExecuteNonQuery();
}
}
}
The database is created successfully. After that, I try to connect to the database to run the initialization script, by using the following code:
private void ExecuteQueryFromFile(string filename)
{
string queryContent = File.ReadAllText(m_filePath + filename);
this.m_connectionString = string.Format(
#"Server=.\SQLExpress; Integrated Security=true;Initial Catalog={0};", m_databaseFilename);
using (var connection = new SqlConnection(m_connectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = queryContent;
command.CommandTimeout = 0;
command.ExecuteNonQuery();
}
}
}
However, the connection.Open() statement fails, throwing the following exception:
Cannot open database "TestData"
requested by the login. The login
failed. Login failed for user
'MYDOMAIN\myusername'.
I am completely puzzled by this error because the account I am trying to connect with has sysadmin privileges, which should allow me to connect any database (notice that I use a connection to the master database to create the database in the first place).
Is there a reason you specify User Instance=True when you create it but not when you try to connect to it?
When you create it after connecting with User Instance, it will create the database files but does not attach it to your actual instance. You'll either have to not specify User Instance=True in the first connection string or add it to the second and specify the database file to use.
Is the user you are logging with have rights to the database 'TestData'?
If not grant the user the privileges required.
I am not sure if this means anything, but in your first create you are connecting to server
.\\sqlexpress
The second one is
.\SQLExpress
You'll need to issue a CREATE USER command (see: http://msdn.microsoft.com/en-us/library/ms173463.aspx) after creating the database but before trying to open a connction to that database.
For example:
CREATE USER 'MYDOMAIN\myusername' FOR LOGIN 'MYDOMAIN\myusername'