Dynamically Create a Generic Type for Template

Missing ProviderName when debugging AzureFunction as well as deploying azure function

So the solution ended up being trivial. The ProviderName attribute specified in local.settings.json MUST be camel case.

From the original git hub discussions :

https://github.com/Azure/azure-functions-cli/issues/46

Shows the provider name as being pascal case

https://github.com/Azure/azure-functions-cli/issues/193

Shows the provider name being camel case in pseudo code
It was very easy to miss but your config section must be exactly as follows

"ConnectionStrings": {
"ShipBob_DevEntities": {
"ConnectionString": "metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string='data source=***;initial catalog=***;persist security info=True;User Id=***;Password=***;;multipleactiveresultsets=True;application name=EntityFramework'",
"ProviderName": "System.Data.EntityClient"
}
}

These points are important:

  • Make sure your connection string has metadata information
  • If copying your string from an xml config, make sure you unescape apostrophes
  • Make sure the ProviderName attribute is camel case
  • Make sure the provider name is System.Data.EntityClient

Fix for missing providername in deployment

Note, this answer assumes you are trying to use the parameterless constructor of a DbContext. If you are creating new code you can easily follow the second upvoted answer

I figured out a way to circumvent the provider name issue while still retaining the use of the portal config and thus deployment slots. It involves setting the default connection string of db context using static properties

private static string _connectionString = "name=ShipBob_DevEntities";

static ShipBob_DevEntities()
{
if(!string.IsNullOrEmpty(System.Environment.GetEnvironmentVariable("AzureFunction")))
{
var connectionString = System.Environment.GetEnvironmentVariable("EntityFrameworkConnectionString");

if (!string.IsNullOrEmpty(connectionString))
{
_connectionString = connectionString;
}
}
}

public ShipBob_DevEntities()
: base(_connectionString)
{
this.Configuration.LazyLoadingEnabled = false;
}

This involves the developer to create an app setting in the azure portal as a flag. In my case it is AzureFunction. This makes sure that our code is only run in an azure function and all other clients of this DbContext, whether they be web apps, windows apps, etc, can still continue behaving as expected. This also involves adding your connection string to the azure portal as an AppSetting and not an actual connection string. Please use the full connection string including them metadata information but without the provider name!

EDIT

You will need to edit your auto generated .tt file t4 template to make sure this code does not get overridden if you are using db first.

Here is a link on the T4 syntax: https://learn.microsoft.com/en-us/visualstudio/modeling/writing-a-t4-text-template

And here is an explanation on EF T4 templates: https://msdn.microsoft.com/en-us/library/jj613116(v=vs.113).aspx#1159a805-1bcf-4700-9e99-86d182f143fe

How to specify EntityFramework ProviderName in an Azure Function

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 like this:

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

With the above code, EF never asks for AppConfig-related config files. But remember, if you have EF entries in your config file, it will attempt to use them, so make sure they're gone.

In terms of azure functions, this means I used the Azure Functions configuration panel in azure to punch in my ConnectionString without the Metadata and providername, and then loaded that in GetDB.

Edit: As per request, here is some explanatory text of the above:
You can't add EF metadata about the connection in Azure Functions, as they do not use an app.config in which to specify it. This is not a part of the connection string, but is metadata about the connection besides 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 above example. You do that by creating a class inheriting from DBConfiguration, and you mark (with an attribute on a partial class) your EF database class with that.

This DBConfiguration contains a different kind of way to instantiate a new database object, in which this metadata is hardcoded, but the connectionstring is retrieved from your app settings in Azure. In this example I just used a static method, but I guess it could be a new constructor also.

Once you have this static method in play, you can use that to get a new database in your database code, like this:

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

This allows you to use EntityFramework without an APP.Config, and you can still change the connectionstring using Azure Functions APP settings.

Hope that helps

Cant connect to Azure SQL from Azure function

You need to provide more code details on how you are setting up your DbContext to have a more personalized answer, but I will give you the following tips:

  1. Use DI as you would use in a normal .NET project with Microsoft's built-in DI container.
    You would need Microsoft.Azure.Functions.Extensions.DependencyInjection
    To do so, use the following configuration:

     [assembly: FunctionsStartup(typeof(Startup))]

    namespace YOUR_NAME_SPACE
    {
    public class Startup : FunctionsStartup
    {
    public override void Configure(IFunctionsHostBuilder builder)
    {
    string SqlConnection =
    Environment.GetEnvironmentVariable("AZURE_SQL_CONNECTIONSTRING");

    builder.Services.AddDbContext<PeopleDbContext>(
    options => options.UseSqlServer(SqlConnection));
    }
    }
    }
  • Make sure you have AZURE_SQL_CONNECTIONSTRING locally in local.settings.json

  1. Make sure your Azure environment is synced, otherwise, this will crash.
    To do so make sure to include the environment variable on the app service environment variables in the portal

enter image description here

enter image description here


  1. Now you can use Dependency Injection to request your context, services that use the context as usual.

Azure Functions: Can compile but cannot run with custom datalayer library

Go to Azure Portal, create a folder called, 'bin' inside your Azure functions using CMD Shell, upload the 'TestDataLayer.dll' file to bin folder which has just been created.

#r "System.Configuration"
#r "System.Data.Entity"
#r "TestDataLayer.dll"

Project structure should look like,

AzureFunctionProjectName001
bin
TestDataLayer.dll
run.csx
project.json
project.lock.json
...

Azure functions should be able to discover your library this time. I believe, EntityFramework works just fine.

Azure Function and PowerShell: unable to set connection strings with Set-AzWebApp

@KetanChawda-MSFT: Thanks for your advice, it helped me a lot to develop the solution (but did not work as such in my context as mentioned below).

Here is the way it works for me now:

$currentConnectionStrings = $app.SiteConfig.ConnectionStrings
$connectionStrings = @{}

# Add existing connection strings
ForEach ($currentConnectionString in $currentConnectionStrings) {
$connectionStrings[$currentConnectionString.Name] =
@{
Value=$currentConnectionString.ConnectionString;
Type=($currentConnectionString.Type | Out-String).ToUpper()
}
}

# Add database connection string
$connectionStrings["connName"] = @{
Value="connString";
Type="SQLAZURE"
}

# Update settings
Set-AzWebApp -ResourceGroupName $resourceGroupName -Name $appName -ConnectionStrings $connectionStrings

What is interesting is that in case of existing connection strings I have to format it as string and use toUpper, otherwise it does not work for me (Error: Set-AzWebApp : Cannot validate argument on parameter 'ConnectionStrings'. Connection string type must be specified.). When adding a new connection string I can use e.g. SQLAZURE as well as SQLAzure.

EDIT:

Here is an approach where you don't need the connection strings section at all when working with Entity Framework and Azure Functions: Missing ProviderName when debugging AzureFunction as well as deploying azure function



Related Topics



Leave a reply



Submit