Azure Function Connection String with database First approch with Entity Framework - entity-framework

I have an Azure Function that uses database first approach connection string. The connection string is located in the local.settings.json file, which contains the sensitive data.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"AzureWebJobsDashboard": "UseDevelopmentStorage=true"
},
"ConnectionStrings": {
"MyConnectionString": "data source=localhost\\sqlexpress;initial catalog=SampleQrCodes;user id=sa;password=****;MultipleActiveResultSets=True;App=EntityFramework"
}
}
If I try removing providerName it gives me the following exception:
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. This will not work correctly.....you pass it to one of the base DbContext constructors that take a DbConnection
Actual connection string (generated from EF):
<add name="DataContext" connectionString="metadata=res://*/EFModel.csdl|res://*/EFModel.ssdl|res://*/EFModel.msl;provider=System.Data.SqlClient;provider connection string="data source=localhost\sqlexpress;initial catalog=SampleQrCodes;user id=sa;password=***;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
Here is similar question Load Connection String from Config File in Azure Functions but it is not working for me how to define this connection string in local.settings.json via database first approach?

According to your description, here is the similar git hub issue. Per my test, you could configure your connection string within the local.settings.json file as follows:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "DefaultEndpointsProtocol=https;AccountName=<account-name>;AccountKey=<account-key>",
"AzureWebJobsDashboard": "DefaultEndpointsProtocol=https;AccountName=<account-name>;AccountKey=<account-key>"
},
"ConnectionStrings": {
"DataContext": {
"ConnectionString": "metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string='data source=<server-name>.database.windows.net;initial catalog=<database-name>;persist security info=True;user id=<username>;password=<password>;MultipleActiveResultSets=True;App=EntityFramework'",
"ProviderName": "System.Data.EntityClient"
}
}
}
For deploying to your azure function, you may need to modify your DbContext. More details, you could refer to this similar issue.

Related

Issue with Entity Framework 6 while connecting to SQL Server from Azure function V2

I am trying to use an existing library which is a .net library which uses EF 6.0 to connect to a database. Since Azure Functions does not have an app.config file, I am trying to set the connection string using C# code. But I am getting the following exception while connecting to the DB using my DB context:
System.ArgumentException: The ADO.NET provider with invariant name 'System.Data.SqlClient' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details.
System.ArgumentException: The specified invariant name 'System.Data.SqlClient' wasn't found in the list of registered .NET Data Providers
MyDBContext.partial.cs:
[DbConfigurationType(typeof(MyDbConfiguration))]
public partial class MyDBContext : DbContext
{
public MyDBContext (string ConnectionString)
: base(ConnectionString)
{
}
}
public class MyDbConfiguration : DbConfiguration
{
public MyDbConfiguration()
{
SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
}
}
I have a method as following to get the DBContext. This method will be used by the library methods to get the DB context instance.
public MyDBContext GetDB( string metadata, string connectionString )
{
EntityConnectionStringBuilder b = new EntityConnectionStringBuilder();
b.Metadata = metadata;
b.ProviderConnectionString = connectionString;
b.Provider = "System.Data.SqlClient";
return new MyDBContext (b.ConnectionString);
}
When I execute a library method to load data from db from an Azure function v2, which internally calls the above method to get DB Context and then connects to actual DB. Here MyDBContext object is getting created, but when it connects to db the following exception occurs.
System.ArgumentException: The ADO.NET provider with invariant name 'System.Data.SqlClient' is either not registered in the machine or application config file, or could not be loaded. See the inner exception for details.
System.ArgumentException: The specified invariant name 'System.Data.SqlClient' wasn't found in the list of registered .NET Data Providers
I just worked on this issue but for Azure function V1.
When using EF with Azure function, you can specify connection string in 'local.settings.json' file like this:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"AzureWebJobsDashboard": ""
},
"ConnectionStrings": {
"YourEntities": {
"ConnectionString": "metadata=res://*/EF.yourModel.csdl|res://*/EF.yourModel.ssdl|res://*/EF.yourModel.msl;provider=System.Data.SqlClient;provider connection string='data source=yourServer;initial catalog=yourDB;persist security info=True;user id=yourUserID;password=yourPwd;MultipleActiveResultSets=True;App=EntityFramework'",
"ProviderName": "System.Data.EntityClient"
}
}
}
Please pay attention to 'ProviderName' attribute. Case should be exact as shown above and provider should be 'EntityClient'
Plus 'Provider Connection String' attribute of actual connection string should be in single quote (I am not sure why Microsoft did this but this is how it is supposed to be).
This will help you run your function app locally with EF without any more changes
Now for deployment in Azure.
local.settings.json does not get deployed to cloud. As its name suggests it acts as configuration file for local run.
So you need to set connection string in 'Configuration' of Azure function app on portal.
There you can specify following parameters:
Name - 'YourEntities'
value - Just Connection string part from above json file
Type - 'Custom'
Slot Settings - according to your requirement
Now if you notice there is no way to specify ProviderName here. If you try to run function now you will get error for 'missing provider name'
Here your extended DBConfiguration class comes in handy.
Create your DB configuration class as below and specify provider as EntityType
public class YourDBContextConfig : DbConfiguration
{
public YourDBContextConfig()
{
SetProviderServices("System.Data.EntityClient",
SqlProviderServices.Instance);
SetDefaultConnectionFactory(new SqlConnectionFactory());
}
}
You can create this class in same file where you have created partial class for your DBContext
Add following attribute to your Context class:
[DbConfigurationType(typeof(YourDBContextConfig))]
Also make sure your partial context class has constructor that takes connection string as parameter and supply it while initializing context:
string connString =
ConfigurationManager.ConnectionStrings["YourEntities"].ConnectionString;
using (YourEntities db = new YourEntities(connString))
{
}
This will work for deployment.

Connection string for PostgreSQL

I am trying to write my connection string in my appsettings.json file and bring it into my startup file through an extension class but I keep getting a
Value cannot be null. Parameter name: connectionString.
I have been using various examples but can't seem to see this new setup with ASP.NET Core 2.2 startup class.`And I'm using PostgreSql
appsetting.json file
{
"PostgreConnectionString": {
"DefaultConnection": "User ID=1;Password=1234;Host=localhost;Port=5432;Database=Demo;Pooling=true;Integrated Security=true;",
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}
}
ServiceExtension.cs
public static void ConfigurePostgreSQL(this IServiceCollection services, IConfiguration config)
{
var connectionString = config["PostgreConnectionString:DefaultConnection"];
services.AddDbContext<RepositoryContext>(options => options.UseNpgsql(config.GetConnectionString(connectionString))); --Error in this line value cannot be null
}
Startup.cs
services.ConfigurePostgreSQL(Configuration);
For .NET Core I use:
_connectionString = config.GetConnectionString("PostgreConnectionString");
config
{
"ConnectionStrings": {
"PostgreConnectionString": "string"
}
}
it works
the problem is the nesting brackets ! Appsettings.json generate a ConnectionStrings object imbricated in "Logging" object.
Put ConnectionStrings out and your Configuration.GetConnectionStrings will works !

Hardcoded EF6 Connectionstring names used from dotnet core

We have an existing .NET Framework library with Entity Framework 6 and static methods like this:
public class OrderManager
{
public static OrderDTO GetOrderByOrderId(int oid)
{
var entities = new MyEntities();
....
}
}
where MyEntities have a hardcoded connectionstring name
internal partial class MyEntities : DbContext
{
public SSE3Entities() : base("name=MyEntities") {}
}
When used in a ASP.NET application, the web.config have a connectionstrings defined like this:
<connectionStrings>
<add name="MyEntities" connectionString="metadata=res://*/M..." providerName="System.Data.EntityClient" />
</connectionStrings>
But how can I reuse this library in a aspnet core application. Tried:
{
"ConnectionStrings": {
"MyEnties": "metadata=res://*/M...",
},
"Logging": {
...
}
}
I know passing the connectionstring into the OrderManager constructor is what we should have done years ago, but changing it now requiers a lot of work.
Are there any ways we can make EF read the new configurations system?
Or could we maybe write some settings to the old ConfigurationManager?
I tried dropping in a web.config without any luck
add System.Configuration.ConfigurationManager from nuget
add a file app.config
.net core applictaion is a consle app, so it find app.config first
app.config:
<appSettings>
<add key="webpages:Version" value="2.0.0.0"/>
</appSettings>
This solution will work for ASPNET Core MVC 2.0, 2.2 and 3.0 In your app root go find the appsetting.json file and modify the connection string.
{
"ConnectionStrings": {
"DefaultConnection": "Data Source=DESKTOP-3R4MR9H\\SQLSERVER3R4MR9;Initial
Catalog=ASPNetCoreMVC;Persist Security Info=True;User
ID=sa;Password=********;"
},
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*"
}

EntityConnection throws the exception when create the connection instance

In my EF project if I execute the following
using (EntityConnection con = new EntityConnection("name=HCMConnection"))
it throws the exception
The specified named connection is either not found in the configuration,
not intended to be used with the EntityClient provider, or not valid.
The connection string is in the Web.Config and it looks like following
<add name="HCMConnection" connectionString="Data Source=DEV-PROG-01;
Initial Catalog=HCM;
user id=HCMUser;
password=*******;
MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
I suspect it does no like the SqlClient provider, does not it?
Thanks.
I believe you should have (replace settings class with the correct one for your app type). There is no EntityConnection constructor that can take the connection string name as a param to work.
using (EntityConnection con = new EntityConnection(SettingsClass.HCMConnection))
However its probably a better idea to let the dbcontext manage the connection instead of doing it manually, this constructor can take just the connection name.
using (MyDbContext con = new MyDbContext ("HCMConnection"))
And even better in your context class
public MyDbContext()
: base("HCMConnection")
Paul
Not clear what is the SettingsClass in my case, but I decided to use the same context to use its connection:
public ActionResult Education(ModelHCMContainer model)
{...
and execute the following
using (DbCommand cmd = model.Database.Connection.CreateCommand())
{
model.Database.Connection.Open();
try
{
cmd.CommandText = String.Concat("select ed.*,", ...
"order by ed.DateStart DESC");
using (var _reader = cmd.ExecuteReader())
{
using (ModelHCMContainer context = new ModelHCMContainer())
{
var records = ((IObjectContextAdapter)context).ObjectContext.Translate<HCMApplication.Models.POCO.Profile.HCMEducationPOCO>(_reader);
items = records.ToList();
}
}
}
finally
{
model.Database.Connection.Close();
}
}
It seems like working fine.
Thanks.

'String cannot have zero length' error when using EF Tracing Data Provider

I am trying to incorporate 'EF Tracing Data Provider' into an existing MVC2 app using VS2010, .NET 4.0 in order to log all SQL commands. I have no interest at this time in the caching provider. I beleive I have followed all the steps listed in the blog posting. BLOG POST My project does compile without error, however when I attempt to run the project I get the following error:
'String cannot have zero length.' The error points to Extended_JCIMS_MVC2_EF_Entities.cs Line: 25
Line 25: public ExtendedJCIMS_DevEntities(string connectionString)
Line 26: :base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
I am unable to determine what is causing this error. I assume the error is referring to the connection string from the Web.Config file. It does not like the 'connectionString' variable. I'm obviously doing something worng. I would appreciate a push in the right direction.
The relevant bits are as follows:
Web.config
--------------------------------------------------------------------------
<add name="JCIMS_DevEntities"
connectionString="metadata=res://*/;provider=System.Data.SqlClient;provider connection string="Data Source=MyServer;Initial Catalog=MyDatabase;User ID=MyUser;Password=myPassWord;MultipleActiveResultSets=True""
providerName="System.Data.EntityClient"/>
<system.data>
<DbProviderFactories>
<add name="EF Tracing Data Provider" invariant="EFTracingProvider" description="Tracing Provider Wrapper"
type="EFTracingProvider.EFTracingProviderFactory, EFTracingProvider, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
<add name="EF Generic Provider Wrapper" invariant="EFProviderWrapper" description="Generic Provider Wrapper"
type="EFProviderWrapperToolkit.EFProviderWrapperFactory, EFProviderWrapperToolkit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=def642f226e0e59b" />
</DbProviderFactories>
</system.data>
Global.ascx
-----------------------------------------------------------------------
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
//EFTracingProviderConfiguration - LOG ALL Sql commands
EFTracingProviderConfiguration.LogToFile = Server.MapPath("~/JCIMS_MVC2_EF_SQL_Logfie.txt");
}
Extended_JCIMS_MVC2_EF_Entities.cs
--------------------------------------------------------------------------
namespace JCIMS_MVC2_EF.DomainModel
{
/// <summary>
/// Partial calss that Extends the EF Datacontext Class
/// </summary>
public partial class ExtendedJCIMS_DevEntities : JCIMS_DevEntities
{
private TextWriter logOutput;
public ExtendedJCIMS_DevEntities()
: this("name=JCIMS_DevEntities")
{
}
public ExtendedJCIMS_DevEntities(string connectionString)
: base(EntityConnectionWrapperUtils.CreateEntityConnectionWithWrappers(
connectionString,
"EFTracingProvider"
))
{
}
//... and more
}
}
SearchRepository.cs
------------------------------------------------------------------
public class SQLSearchRepository : ISearchRepository
{
//Database connection
private ExtendedJCIMS_DevEntities db = new ExtendedJCIMS_DevEntities(); // tracing version
public IEnumerable<SearchResults> ListAll(string strSearch, string chkSearch)
{
return (from s in db.Schools....
// and more...
}
Appreciate any assistance anyone can give me...
Have you debugged and confirmed that the connectionString passed into the ExtendedJCIMS_DevEntities method is not null or empty? That's what the error seems to indicate.