Connection to Entity Framework works locally, Was working in Azure but now I get "Invalid object name..." - azure

I have looked through various posts related to this problem, but none provide an answer. I created a .Net 5.0 app that accesses an Azure SQL DB using EF 6.4.4 which works with .Net standard libraries. I modified the EF by adding a function that creates the connection string from appsettings.json since .Net 5 apps don't use a web.config file. This also works well in Azure with the configuration settings in an app service.
The connection string looks like this:
metadata=res://*/EF.myDB.csdl|res://*/EF.myDB.ssdl|res://*/EF.myDB.msl;provider=System.Data.SqlClient;provider connection string='Data Source=tcp:mydb.database.windows.net,1433;Initial Catalog=myDB;Integrated Security=False;Persist Security Info=False;User ID=myuserid#mydb;Password="password";MultipleActiveResultSets=True;Connect Timeout=120;Encrypt=True;TrustServerCertificate=True'
I also have a deployment pipeline that will deploy the code after a check-in instead of using the Visual Studio publish feature, but the pipeline deployed code has the same problem.
When I first created the app and published it to the app service, it worked. Recently I updated the app with no changes to the EF connection. Now I get the "Invalid Object name when I reference any table in the model. If I run the same code locally and connect to the Azure SQL DB, the DB is accessed as expected. This problem only occurs when running in the Azure app service. Note that there are no connection strings configured for the app service since the EF string is built from the config settings. I saw this post, but I don't think it applies:
Local works. Azure give error: Invalid object name 'dbo.AspNetUsers'. Why?
even though the problem is the same. I have also read various posts about the format of the EF connection string. Since my model is database first, (and the connection used to work), I'm confident the string has the correct format. I don't think the problem is in the code since it works when running locally with a connection to the Azure SQL DB. It must have something to do with the Azure app service configuration, but I'm not sure what to look for at this point. Unfortunately I don't have a copy of the code and publish files that did work to compare to, but it the pipeline build doesn't work either and that it how the code would normally be deployed. Thanks for any insight you might have!

UPDATE
metadata=res://*/EF.myDB.csdl|res://*/EF.myDB.ssdl|res://*/EF.myDB.msl;provider=System.Data.SqlClient;provider connection string='Data Source=tcp:yourdbsqlserver.database.windows.net,1433;Initial Catalog=yourdb;Persist Security Info=False;User ID=userid;Password=your_password;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30'
When the troubleshooting problem is not on the string, our easiest way is to use vs2019 to re-use the generated string.
Your connection string should be like below.
<connectionStrings>
<add name="SchoolDBEntities" connectionString="metadata=res://*/SchoolDB.csdl|res://*/SchoolDB.ssdl|res://*/SchoolDB.msl;provider=System.Data.SqlClient;provider connection string="data source=.\sqlexpress;initial catalog=SchoolDB;integrated security=True;multipleactiveresultsets=True;application name=EntityFramework"" providerName="System.Data.EntityClient"/>
</connectionStrings>
For more details, you can refer my answer in the post and the tutorial.
1. Timeout period elasped prior to obtaining a connection from the pool - Entity Framework
2. Entity Framework Tutorial

The problem was one of my config settings in Azure. The catalog parameter was missing. A simple fix, but the error message was misleading, so I thought I would note that here in case anyone else gets the same "Invalid object name" message when referencing an Azure SQL DB with EF. It would have been more helpful if the message was "catalog name invalid" or "unable to connect to database".
For those who are curious about building an EF connection string, here is example code:
public string BuildEFConnectionString(SqlConnectionStringModel sqlModel, EntityConnectionStringModel entityModel)
{
SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
{
DataSource = sqlModel.DataSource,
InitialCatalog = sqlModel.InitialCatalog,
PersistSecurityInfo = sqlModel.PersistSecurityInfo,
UserID = sqlModel.UserID, // Blank if using Windows authentication
Password = sqlModel.Password, // Blank if using Windows authentication
MultipleActiveResultSets = sqlModel.MultipleActiveResultSets,
Encrypt = sqlModel.Encrypt,
TrustServerCertificate = sqlModel.TrustServerCertificate,
IntegratedSecurity = sqlModel.IntegratedSecurity,
ConnectTimeout = sqlModel.ConnectTimeout
};
//Build an Entity Framework connection string
EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
{
Provider = entityModel.Provider, // "System.Data.SqlClient",
Metadata = entityModel.Metadata,
ProviderConnectionString = sqlString.ToString()
};
return entityString.ConnectionString;
}
Given what I have learned, the properties should be validated before the string is returned. If the string is created this way, all of the connection string properties can be added to the config settings in the app service. I used the options pattern to get them at runtime. Thanks to everyone for your suggestions.

Related

Invalid resource name creating a connection to azure storage

I'm trying to create a project of the labeling tool from the Azure form recognizer. I have successfully deployed the web app, but I'm unable to start a project. I get this error all every time I try:
I have tried with several app instances and changing the project name and connection name, none of those work. The only common factor and finding here as that it is related to the connection.
As I see it:
1) I can either start a new project or use one on the cloud:
First I tried to create a new project:
I filled the fields with these values:
Display Name: Test-form
Source Connection: <previuosly created connection>
Folder Path: None
Form Recognizer Service Uri: https://XXX-test.cognitiveservices.azure.com/
API Key: XXXXX
Description: None
And got the error from the question's title:
"Invalid resource name creating a connection to azure storage "
I tried several combinations of names, none of those work.
Then I tried with the option: "Open a cloud project"
Got the same error instantly, hence I deduce the issue is with the connection settings.
Now, In the connection settings I have this:
At first glance, since the values are accepted and the connection is created. I guess it is correct but it is the only point I failure I can think of.
Regarding the storage container settings, I added the required CORS configuration and I have used it to train models with the Forms Recognizer, So that part does works.
At this point at pretty much stuck, since I error message does not give me many clues on where is the error.
I was facing a similar error today
You have to add container name before "?sv..." in your SAS URI in connection settings
https://****.blob.core.windows.net/**trainingdata**?sv=2019-10-10..

Azure SQL serverless is not waking up on connection attempt

I'm testing Azure SQL Serverless and from SSMS it seems to work fine, but from my ASP.NET Core application it never wakes up.
Using SSMS I can open a connection to a sleeping Serverless SQL database and after a delay the connection will go through.
Using my ASP.NET Core application I tried the same. From the login page I tried to login, which opens a connection to the database. After 10 or 11 seconds (I looked up the default timeout and its supposed to be 15 seconds but in this case it always seems to be about 10.5 seconds +/-0.5s). According to the docs, the first connection attempt may fail but subsequent ones should succeed, but I can send multiple queries to the database and it always fails with the following error:
Microsoft.Data.SqlClient.SqlException (0x80131904): Database 'myDb' on server
'MyDbSvr.database.windows.net' is not currently available. Please retry the connection later. If the
problem persists, contact customer support, and provide them the session tracing ID of
'{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}'.
If I wake the database up using SSMS then the login web page can connect to the database and succeeds.
I have added Connect Timeout=120; to the connection string.
The connection does happen during an HTTP request that is marked async on the Controller, thought I don't know if that makes any difference.
Am I doing something wrong or is there something additional I need to do to get the DB to wake?
[updte]
as an extra test wrote the following test
void Main()
{
SqlConnection con = new SqlConnection("Server=mydbsvr.database.windows.net;Database=mydb;User Id=abc;Password=xyz;Connect Timeout=120;");
Console.WriteLine(con.ConnectionTimeout);
con.Open();
var cmd = con.CreateCommand();
cmd.CommandText = "select getdate();";
Console.WriteLine(cmd.ExecuteScalar());
}
and got the same error.
I figured it out and its the dumbest thing.
This Azure SQL Server instance was migrated from another subscription and the group that migrated it gave it a new name, but they did something that allowed the use of the old name also. I'm researching to figure out how that was done. I will update this answer when I find out what that was.
As it turns out, using the old name with an Serverless Database won't wake up the db. Don't know why. But if you change to use the new/real server name it works. you do have to add a retry to the connection as it may fail the first few times.
[Update]
The new server allows logins using the old name by using a Azure SQL Database Alias https://learn.microsoft.com/en-us/azure/sql-database/dns-alias-overview

Connecting worker role with EF 6 to Azure sql database

I'm trying to set up a worker role to read and act based on data from Azure sql database.
I set the connection string like this:
public DBEntities(string connectionString) : base(connectionString) {}
Whenever I try to run the worker role localy I get the following error when querying the entities:
System.Data.Entity.Infrastructure.UnintentionalCodeFirstException: 'The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development.
To query the entities:
using (ctx = new CODDBEntities(_connectionString))
{
var result = ctx.entity.ToList().FindAll();
}
What am I doing wrong?
It seems that you're specifying the Database Initialization Strategies.
Try the Following:
public CODDBEntities()
{
Database.SetInitializer<CODDBEntities>(null);//Disable initializer
}
more info in here: http://www.entityframeworktutorial.net/code-first/database-initialization-strategy-in-code-first.aspx
Finnaly I got it. Using this article I understood that I was using the wrong connection string type. I needed to use the one starting like - metadata=res://*/..." while I just coiped the default connection string from the Azure portal.

SqlDataProvider connection string in Suave on Azure

I can't get SqlDataProvider to work when executed in a fsx script which is running in an Azure Web Site.
I have started from the samples that Tomas Petrecek has here: https://github.com/tpetricek/Dojo-Suave-FsHome.
In short it is a FSX script that is executed using the IIS httpPlatformHandler so that all http requests to my Azure Web site is forwarded to my F# script.
The F# Script use Suave to handle the requests.
When I tried adding some database access to my HTTP handlers I got into problems.
The problematic code looks like this:
[<Literal>]
let connStr = "Server=(localdb)\\v11.0;Initial Catalog=My_Database;Integrated Security=true;"
[<Literal>]
let resolutionFolder = __SOURCE_DIRECTORY__
FSharp.Data.Sql.Common.QueryEvents.SqlQueryEvent |> Event.add (printfn "Executing SQL: %s")
// the following line fails when executing in azure
type db = SqlDataProvider<connStr, Common.DatabaseProviderTypes.MSSQLSERVER, ResolutionPath = resolutionFolder>
let saveData someDataToSave =
let ctx = db.GetDataContext(Environment.GetEnvironmentVariable("SQLAZURECONNSTR_QUERIES"))
.....
/// code using the context here
This works just fine when I run it locally, but when I deploy it to the azure site it will fail at the line where the type dbis created.
The error message is (line 70 is the line that has the type db = ...:
D:\home\site\wwwroot\app.fsx(70,11): error FS3033: The type provider
'FSharp.Data.Sql.SqlTypeProvider' reported 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: SQL Network Interfaces, error: 52
- Unable to locate a Local Database Runtime installation. Verify that SQL Server Express is properly installed and that the Local Database
Runtime feature is enabled.)
The design-time database in the connStr is not available in the azure site, but I thought this is why we have the GetDataContext overload that takes a connection string to be used at run-time?
Is it because it is running as a script and not as compiled code that it is trying to access the database when creating the TypeProvider?
If yes, does it mean that my only option is to compile and provide the database code as a compiled assembly that I load and use in my Suave FSX script?
Reading the connection string from a config file does not work very well as this is in a azure site. I really need to get the connection string from an environment variable (which is set in the azure management interface).
Hmm, this is a bit unfortunate - as #Fyodor mentioned in the comments, the problem is that the script-based deployment to Azure actually compiles the script on the Azure machine - and so you need to have a statically-resolved connection string that works on Azure.
There are two options:
Use compiled project instead. If you compile your F# code locally and deploy the compiled code to Azure it will work. Sadly, there are no good samples for that.
Do some clever trick to make the connection string accessible to the script at compile time.
Send a PR to the SQL provider so that you can give it the name of an environment variable and it reads the connection string from there.
I think (3) would actually be quite nice and useful feature.
I'm not necessarily sure what the best way to do (2) would be. But I think you might be able to modify app.azure.fsx so that it creates a file (say connection.fsx) that contains something like:
module Connection
let [<Literal>] ConnString = "<Contents of SQLAZURECONNSTR_QUERIES>"
Then app.fsx could load this script and use Connection.ConnString in the argument of SQL type provider.

How to configure Quartz.net to use an Azure SQL database to store ADOJobStore details

I am using quartz.net as a scheduler in a Microsoft Azure Web Role. I can get Quartz.net to work just fine if I use the RamDataStore. However, I want to break this into two components: the first will allow scheduling of jobs through a web interface and the second will execute the jobs through a worker role. To have this distributed processing, I will need to use an ADOJobStore.
Everything works fine with the RamDataStore but it breaks when I try to switch over to the ADOJobStore. So this leads me to believe that there is something in my properties that I'm missing. I am using Azure SQL database and while this is similar to SQL Server, there are some gotchas that sometimes cause problems.
I am using Quartz.net 2.0 (from nuGet) in VS2010, the database is Azure SQL.
When I call .GetScheduler(), I get the following exception:
{"JobStore type 'Quartz.Impl.AdoJobStore.JobStoreTX' props could not
be configured."}
with the details:
{"Could not parse property 'default.connectionString' into correct
data type: No writable property 'Default.connectionString' found"}
My connection code (including programatically set properties):
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "SchedulingServer";
properties["quartz.threadPool.type"] = "Quartz.Simpl.ZeroSizeThreadPool, Quartz";
properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
properties["quartz.jobStore.tablePrefix"] = "QRTZ_";
properties["quartz.jobStore.clustered"] = "false";
properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";
properties["quartz.jobStore.dataSource"] = "default";
properties["quartz.jobStore.default.connectionString"] = "Server=tcp:serverName.database.windows.net;Database=scheduler;User ID=scheduler#serverName;Password=***;Trusted_Connection=False;Encrypt=True;";
properties["quartz.jobStore.default.provider"] = "SqlServer-20";
properties["quartz.jobStore.useProperties"] = "true";
ISchedulerFactory sf = new StdSchedulerFactory(properties);
_scheduler = sf.GetScheduler();
Any help or suggestions would be appreciated.
You have small but subtle error in your data source property naming, it should read:
properties["quartz.dataSource.default.connectionString"] = "Server=tcp:serverName.database.windows.net;Database=scheduler;User ID=scheduler#serverName;Password=***;Trusted_Connection=False;Encrypt=True;";
Also there is a property connectionStringName if you want to use the connection string section of configuration file.

Resources