How to specify EntityFramework Provider Name in Azure Function

I am trying to port some webjob code to new Azure features. So far, I managed to import my DLL and refer to them successfully, but when I use the connection string in my code, I get an error: I have to add the name Provider:

The connection string 'ConnectionString' in the application configuration file does not contain the required attribute name provider. "

This is usually not a problem, because in a webjob (or web application) it will be in App or Web.config, and the connection string will simply be rewritten with what I entered in Azure.

With Azure functions, I don’t have a web.config file (although I tried to add it to no avail), so, naturally, the provider name is missing.

How to indicate this?

EDIT: After some games and some helpful tips from the people below, I almost managed to get it to work.

Now I do the following:

var connString = **MY CONN STRING FROM CONFIG**; // Constring without metadata etc. EntityConnectionStringBuilder b = new EntityConnectionStringBuilder(); b.Metadata = "res://*/Entities.MyDB.csdl|res://*/Entities.MyDB.ssdl|res://*/Entities.MyDB.msl"; b.ProviderConnectionString = connString.ConnectionString; b.Provider = "System.Data.SqlClient"; return new MyDB(b.ConnectionString); 

This gives me what I need to call the database. I use a static method in a partial class to get an instance of a database that runs the above code, and I decorate MyDB Partial with [DbConfigurationType(typeof(MyDbConfiguration))]

I define this configuration as:

 public class MyDBConfiguration: DbConfiguration { public MyDBConfiguration() { SetProviderFactory("System.Data.EntityClient", EntityProviderFactory.Instance); } } 

My problem remains when I want to actually use EF objects. Here he will try to initialize the database type using the original configuration, giving me the original error again. According to this stack trace:

 at Void Initialize() at System.Data.Entity.Internal.EntitySetTypePair GetEntitySetAndBaseTypeForType(System.Type) at Void InitializeContext() at System.Data.Entity.Core.Objects.ObjectContext CreateObjectContextFromConnectionModel() at Void Initialize() at Boolean TryInitializeFromAppConfig(System.String, System.Data.Entity.Internal.AppConfig) at Void InitializeFromConnectionStringSetting(System.Configuration.ConnectionStringSettings) 

So, how can I avoid this? I think I need a way to connect to everything and run my custom setter.

+6
source share
5 answers

In the end, Stephen Reindel pushed me in the right direction; Code Based Configuration for Entity Framework.

 [DbConfigurationType(typeof(MyDBConfiguration))] public partial class MyDB { public static MyDB GetDB() { var connString = **MY CONN STRING FROM SOMEWHERE**; // Constring without metadata etc. EntityConnectionStringBuilder b = new EntityConnectionStringBuilder(); b.Metadata = "res://*/Entities.MyDB.csdl|res://*/Entities.MyDB.ssdl|res://*/Entities.MyDB.msl"; b.ProviderConnectionString = connString.ConnectionString; b.Provider = "System.Data.SqlClient"; return new MyDB(b.ConnectionString); } public MyDB(string connectionString) : base(connectionString) { } } 

With MyDbConfiguration as follows:

 public class MyDBConfiguration: DbConfiguration { public MyDBConfiguration() { SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance); SetDefaultConnectionFactory(new SqlConnectionFactory()); } } 

With the above code, EF never queries the configuration files associated with AppConfig. But remember , if you have EF entries in your configuration file, it will try to use them, so make sure they are gone.

In terms of azure features, this means that I used the Azure Functions configuration panel in azure to punch in my ConnectionString without metadata and provider name, and then uploaded them to GetDB.

Edit: as requested, the following explanatory text is given above: You cannot add EF connection metadata to Azure Functions, since they do not use app.config in which you can specify it. This is not part of the connection string, but represents connection metadata, except for the connection string that EF uses to map to a specific C # class and SQL provider, etc. To avoid this, you hardcode it using the example above. You do this by creating a class that inherits from DBConfiguration, and you mark (with an attribute on the partial class) your EF database class with this.

This DBConfiguration function contains another way to create a new database object in which this metadata is hard-coded, but the connection string is extracted from your application settings in Azure. In this example, I just used the static method, but I think it could be a new constructor.

Once you have this static method in the game, you can use it to get the new database in your database code, for example:

 using (var db = MyDB.GetDB()) { // db code here. } 

This allows you to use EntityFramework without APP.Config, and you can still change the connection string using the Azure APP function parameters.

Hope that helps

+5
source

Using this question , you can set your factory by default before opening a connection, having your own personal DbConfiguration class (see this link also for use):

 public class MyDbConfiguration : DbConfiguration { public MyDbConfiguration() { SetDefaultConnectionFactory(new SqlConnectionFactory()); } } 

Now you need to tell DbContext use the new configuration. Since using web.config or app.config is not a parameter, you can use the attribute to add the configuration:

 [DbConfigurationType(typeof(MyDbConfiguration))] public class MyContextContext : DbContext { } 

Now, using the connection string on DbContext , it will use the SQL provider by default.

+2
source

Adding an answer in case you cannot just change the way you create an instance of DbContext . This will happen if you invoke code for which DbContexts is set using the constructor without parameters.

It includes using a static constructor to read your connection string from the application settings in the azure portal and pass it to your base DbContext constructor. This circumvents the need for providerName , and also saves the use of portal configuration without the need for hard code.

Take a look at my accepted answer here: Missing provider name when debugging AzureFunction, as well as deploying the azure function

+1
source

Provided that the answer is perfect, and it helped me a lot, but it is not dynamic, since I do not want to hard-code my connection string. if you work with slots in azure functions. I was looking for a solution in which I can use more than 1 connection string. Here is my alternative approach step by step for someone else who is struggling with this problem.

  • Most importantly, we understand the local.settings.json file is NOT FOR LIFE. this is to run your application locally, as the name is clear. Therefore, the solution has nothing to do with this file.

  • App.Config or Web.Config do not work for Azure connection strings. If you have a Layer Layer library, you cannot overwrite the connection string using any of them, as in Asp.Net applications.

  • To work, you need to define a connection string on the azure portal under Application Settings in your Azure function. There are Connection Strings. there you must copy the connection string of your DBContext. if it is edmx, it will look like below. There is a connection type, I use it with SQlAzure, but I tested it using Custom (someone claimed that it works only with the normal one) works with both.

metadata = resolution: ///Models.myDB.csdl | Res: ///Models.myDB.ssdl | Res: //*/Models.myDB.msl; provider = System.Data.SqlClient; provider connection string = 'data source = [yourdbURL]; catalog = myDB; security information is saved = True; user ID = xxxx, password = xxx, MultipleActiveResultSets = True; App = EntityFramework

  1. After you install this, you need to read the URL in your application and provide the DBC text. DbContext implements a constructor with a connection string parameter. By default, the constructor has no parameter, but you can extend it. if you use the POCO class, you can just change the DbContext class. If you use classes created in Edmx, such as me, you do not want to touch the automatically created edmx class instead of creating a partial class in the same namespace and extending this class as shown below.

This is an automatically generated dbcontext

 namespace myApp.Data.Models { public partial class myDBEntities : DbContext { public myDBEntities() : base("name=myDBEntities") { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { throw new UnintentionalCodeFirstException(); } } 

this is a new partial class, you create

 namespace myApp.Data.Models { [DbConfigurationType(typeof(myDBContextConfig))] partial class myDBEntities { public myDBEntities(string connectionString) : base(connectionString) { } } public class myDBContextConfig : DbConfiguration { public myDBContextConfig() { SetProviderServices("System.Data.EntityClient", SqlProviderServices.Instance); SetDefaultConnectionFactory(new SqlConnectionFactory()); } } } 
  1. In the end, you can get the connection string from the azure settings in your Azure Function project with the code below and provide your DbContext myDBEntities - the name you specified on the azure portal for your connection string.
 var connString = ConfigurationManager.ConnectionStrings["myDBEntities"].ConnectionString; using (var dbContext = new myDBEntities(connString)) { //TODO: } 
+1
source

You can access the site’s application settings by going to the portal by clicking Function app settings and then Configure app settings . This will open the blade, which allows you to set all the application settings for your functional application. Just use the same key and value that you will use for your web.config.

0
source

All Articles