Resolving connection string in EFv6.3 in ASP.NET Core Windows service project - entity-framework

I have an ASP.NET Core application running as a Windows Service. Due to project requirements, I am using Entity Framework v6.3 (as opposed to using EF Core).
I am having trouble retrieving the correct connection string when performing a migration and also upon publishing the service to a server. When running the service locally, the connection string is retrieved successfully.
As I understand it, Entity Framework 6 is supposed to retrieve connection strings from web.config or app.config files, right? Therefore, I have an app.config file containing two connection strings, e.g.
<connectionStrings>
<add name="DataContext" providerName="System.Data.SqlClient" connectionString="Server=localhost\SQLEXPRESS;[redacted]" />
<add name="CrmContext" providerName="System.Data.SqlClient" connectionString="Server=localhost\SQLEXPRESS;[redacted]" />
</connectionStrings>
In my Startup class, I have registered both database contexts, e.g.
services.AddTransient<DataContext>();
services.AddTransient<CrmContext>();
On a Razor page, when I instantiate both data contexts on my local machine I can see the correct connection string is being resolved for both contexts (by using _crmContext.Database.Connection.ConnectionString).
When I attempt to add a migration using the update-database command on my CrmContext (automatic migrations enabled), the correct connection string isn't resolved. Instead, it defaults to creating a LocalDB database using the default connection string: (localdb)\MSSQLLocalDB
How come it isn't using the connection string I have provided in my app.config file? I also a web.config file but it doesn't resolve from there either.
CrmContext.cs
public class CrmContext : DbContext
{
public CrmContext() : base("CrmContext")
{
Database.SetInitializer<CrmContext>(null);
}
public IDbSet<CustomerDetails> CustomerDetails { get; set; }
}
CrmConfiguration.cs
internal sealed class CrmConfiguration : DbMigrationsConfiguration<CrmContext>
{
public CrmConfiguration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(CrmContext context)
{
...
context.SaveChanges();
}
}
I've tried to explicitly update the CRM connection by specifying my CrmConfiguration file:
update-database -ConfigurationTypeName CrmContext
When I do this, it creates and updates the LocalDB database instead of using my connection string.
I've also tried to explicitly referencing the connection string:
update-database -ConnectionStringName "CrmContext"
This results in this error:
No connection string named 'CrmContext' could be found in the
application config file.
My CrmContext class exists within my ASP.NET Core windows application where my DataContext class exists in a separate 'Data' project (as it's shared with an ASP.NET MVC v5 application)
When I publish my service and install the application as a Windows Service, I found that it also doesn't pick up the connection strings at all from any of the config files - it again just looks for the default localdb database. As I understand, it should pick it up from my PaymentBatchProcessorService.exe.config file, right?
My PaymentBatchProcessorService.exe.config file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="DataContext" providerName="System.Data.SqlClient" connectionString="redacted" />
<add name="CrmContext" providerName="System.Data.SqlClient" connectionString="redacted" />
</connectionStrings>
</configuration>
As per Microsoft documentation, it should be possible to load in the additional XML configuration files via the following code in the Program.cs file, but EntityFramework still didn't pick up the connection strings:
Host.CreateDefaultBuilder(args)
.UseWindowsService()
.ConfigureAppConfiguration((hostingContext, config) =>
{
var workingDirectoryPath = Environment.GetEnvironmentVariable(EnvironmentVariables.ServiceWorkingDirectory);
config.AddXmlFile(Path.Combine(workingDirectoryPath, "app.config"));
config.AddXmlFile(Path.Combine(workingDirectoryPath, "web.config"));
})
e.g. in the above sample, the working directory path resolves to the location where my .exe is for the Windows Service.
Thanks for reading this far!

When you deploy your service, the .config file should instead be called servicename.exe.config. It should reside on the same folder where the service was registered with installutil. See Windows service app.config location.

Related

Azure Api/Web App with Entity Framework - SQL database connection string

I'm adding an SQL database to my Azure API App. I have an empty SQL database which I created separately via portal.azure.com. My problem is I don't know how to set up the connection string so that my app uses the Azure database.
I have followed the Code First Migrations article, but I'm stuck on the deployment phase. I cannot see any connection configuration in any of the files in the project.
How do I set the connectionString to be used by the app when it's deployed in Azure?
More info:
To be precise, I can see 2 things:
Commented out connectionStrings sections in Web.Debug/Release.config files.
Some EF configuration in Web.Config:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
(...)
When I execute tests locally I can see Database.Connection.ConnectionString is
Data Source=(localdb)\mssqllocaldb;Initial Catalog=XDataAPI.Models.MyContext;Integrated Security=True;MultipleActiveResultSets=True
BTW. The publish window states that no database have been found in the project. (This doesn't really bother me, it's a secondary issue)
Edit:
DbContext, as requested:
public class MyAppContext : DbContext
{
public DbSet<Organisation> Organisations { get; set; }
}
Pass in the connection name as param to your constructor, and then use the same connection name when setting up your connection string in your web.config, like this:
public class MyAppContext : DbContext
{
public MyAppContext():base("MyConnectionName"){}
public DbSet<Organisation> Organisations { get; set; }
}
And then, in web.config:
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="MyConnectionName" connectionString="Server=tcp:test.database.windows.net,1433;Database=testdb;User ID=test#test;Password=p4ssw0rd!;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
providerName="System.Data.SqlClient" />
</connectionStrings>
....
<configuration>
If you want to run from a local machine, remember that you need to allow incoming connections from your IP on your Azure database server firewall.
If you set up the SQL Server VM, then
<add name="DataContext" connectionString="Data Source=VMname.cloudapp.net; Initial Catalog=catalog; User ID=login;Password=password; MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
If you set up the SQL Azure, then that tutorial should be used.
As for the connection string place, please refer to some documentation. You use LocalDB, instead of that you should use the SQL Server.
You should be able to just update the connection string for your data context in the web.config to use you Azure SQL Database. For my testproject it is just at the top of web.config:
<configuration>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<connectionStrings>
<add name="WebApplication4Context" connectionString="Server=tcp:test.database.windows.net,1433;Database=testdb;User ID=test#test;Password=p4ssw0rd!;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
providerName="System.Data.SqlClient" />
</connectionStrings>
....
<configuration>
Don't forget to also update the firewall settings of your Azure SQL Database Server to make it accessible for your application.
Edit: You can also change the database connection for just your Azure environment by adding the your Azure SQL DB in the Publish dialogue:
If the connection string is missing web.config, then it is using the default name which is DefaultConnection and it refers to the localdb instance that gets installed with SQL or SQL Express.
To configure it, you have to first create a SQL DB on Azure, from the Portal, create a new database and give it a name and make sure it exist in the same resource group and region to decrease the latency and improve the performance.
Open the created database and you will find the connection string for many platforms, copy the one for .Net and go to the Web App settings, you should find a place for connection strings, add a new one and name it DefaultConnection and add the value a the connection string you just copied from the database blade
When you run the application for the first time, code first will connect to the database and apply the migration if you specified that during the publish wizard which adds some configuration in web.config as well.
For .Net FW 4.5 or above:
1. Your DbContext class:
public class MyAppContext: DbContext
{
public MyAppContext() : base("YourConnectionStringKey") { }
public DbSet<Organization> Organizations{ get; set; }
}
2. Your Web.config:
<connectionStrings>
<add name="YourConnectionStringKey" connectionString="DummyValue" providerName="System.Data.SqlClient" />
</connectionStrings>
3. In your Azure WebApp settings, add the connection string (which will be automatically injected into your Web.config at runtime)
If you're not developing using the .Net framework, see https://azure.microsoft.com/en-us/blog/windows-azure-web-sites-how-application-strings-and-connection-strings-work/ for further details.

Microsoft.Practices.EnterpriseLibrary.Data.DLL but was not handled in user code

Searched google and using Enterprise library data access to connect database.
Installed only data access pack using https://www.nuget.org/packages/EnterpriseLibrary.Data/.
After added to the project, I've set the configuration as follows,
<configSections>
<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="false" />
</configSections>
<dataConfiguration defaultDatabase="dProvider" />
<connectionStrings>
<add name="dProvider" connectionString="server=local;Initial Catalog=n;uid=sa;pwd=pwd"
providerName="System.Data.SqlClient" />
</connectionStrings>
Called through the application like the following,
Database db;
string sqlCommand;
DbCommand dbCommand;
db = DatabaseFactory.CreateDatabase("dProvider"); or DatabaseFactory.CreateDatabase();
After run the application, I got the following exception,
{"Database provider factory not set for the static DatabaseFactory. Set a provider factory invoking the DatabaseFactory.SetProviderFactory method or by specifying custom mappings by calling the DatabaseFactory.SetDatabases method."}
What mistake I made ? How to solve this issue ?
Finally found the answer. It has been occurred because of the configuration section.
I've used version 6, but here I've mentioned like version 5 in the configuration section. So the error has occurred.
I've replaced the configuration section like following, It worked perfectly in good way. :-). Thanks a lot for the helpers.
<configSections>
<section name="dataConfiguration"
type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings,
Microsoft.Practices.EnterpriseLibrary.Data"/>
</configSections>
and used DataBaseProviderFactory class to create instance.
DatabaseProviderFactory factory = new DatabaseProviderFactory();
db = factory.Create("dProvider");

Use Entity Framework Code first with any database

I use SQL Server developer edition and would like to use EF code first. I found many articles explaining how to work with either a localdb or SQLExpress. How do I tell my project to rather use my ..\SQL2008 instance?
I'm thinking that somewhere, somehow, one must be able to tell the project to use a specific connectionstring. But where? Adding it to my app.config file doesn't work. This is what I've tried:
<connectionStrings>
<add name="Context" connectionString="Integrated Security=SSPI;Persist Security Info=False;Initial Catalog=TimeApp;Data Source=Amanda-PC\SQL2008; MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/>
</connectionStrings>
You can specify which connection string to use by passing the name of the connection string to the DbContext.
public class YourContext : DbContext
{
public YourContext()
: base("Context")
{
}
}
See this for more information

Entity Framework Code First Azure connection

I am using Entity Framework Code First 4.3 + Azure and having difficulties connecting to the database. The error I get is the following (on the first query):
Keyword not supported: 'server'.
I have the following connection set up in my Web.config
<configSections>
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</configSections>
<connectionStrings>
<add name="TestDBContext"
connectionString="Server=tcp:[SUBSCR].database.windows.net,1433;Database=[MyDB];User ID=[user];Password=[pass];Trusted_Connection=False;Encrypt=True;PersistSecurityInfo=True"
providerName="System.Data.EntityClient" />
</connectionStrings>
My DbContext implementing class uses the connection string's name:
public class MyContext : DbContext, IMyContext
{
public MyContext()
: base("TestDBContext")
{
Configuration.LazyLoadingEnabled = true;
Configuration.ProxyCreationEnabled = true;
}
Can you tell what is going on?
I just had the same problem.
You're missing all the metadata in the connection string that Entity Framework requires. The connection string provided by SQL Azure needs to inserted within the provider connection string parameter of EF's connection string.
<add name="MyConnectionString" connectionString="metadata=res://*/Model.Model.csdl|res://*/Model.Model.ssdl|res://*/Model.Model.msl;provider=System.Data.SqlClient;provider connection string="[PUT SQL AZURE CONN STRING HERE]"" providerName="System.Data.EntityClient" />
You'll need to use the metadata from your own project. I pulled that metadata from an EF project generating from an existing database.
I had the same problem. I solved, putting in the web.config this connectionstring:
<add name="eManagerTurModelConnection" connectionString="metadata=res://*/ORM.eManagerFinanceModel.csdl|res://*/ORM.eManagerFinanceModel.ssdl|res://*/ORM.eManagerFinanceModel.msl;provider=System.Data.SqlClient;provider connection string="Data Source=<server>.database.windows.net;Initial Catalog=eManagerTur;Integrated Security=False;User ID=<user>;Password=<Password>;Connect Timeout=15;Encrypt=False;TrustServerCertificate=False;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" />
And after I removed the connectionstring of my website, worked, because it was not getting the connection string that I added in my web.config.
English bad... =)
The provider should be providerName="System.Data.SqlClient"
I connected to Azure from VS and then looked at the properties and set my connection string and provider name.
<add name="context" connectionString="Data Source=myServer,myPort;Initial Catalog=myDBName;Persist Security Info=True;User ID=myUserName;Password=myPassword;" providerName="System.Data.SqlClient"/>
I was then able to run update-database with no issues.
i tried like this, it may help you. may be 1433 is making problem, is it port no ? or what? . try like this.
check this link Windows Azure with Sql
<add name="dbContext" connectionString="Server=tcp:xxxxxxxx.database.windows.net;Database=xxxxxxxx;User ID=xxxxxxx#xxxxxxxxx;Password=xxxxxxxxxx;Trusted_Connection=False;Encrypt=True;" providerName="System.Data.EntityClient" />
Try this:
Data Source=tcp:YOUR-DATABASE-HERE.database.windows.net,1433;
Database=GolfRounds;
User ID=YOUR-USERNAME#YOUR-SERVER; Password=YOUR-PASSWORD; Trusted_Connection=False; Encrypt=True;
There is also an MSDN article at http://msdn.microsoft.com/en-us/library/windowsazure/ff951633.aspx that may be helpful.
I had a similar problem where I did not have access to the metadata, in this case you need to use System.Data.SqlClient as the provider. You will also need to add MultipleActiveResultSets=True to your connection string

How to change EF default from SQL Server Express db creation to local SQL Server 2008 Instance?

Can somebody tell me how I can setup my MVC3 applciation so that when it first creates a database that it does so in a local (or remote) instance of SQL Server 2008 instead of using SQL Server Express?
So if you're using EF, then you will use a class to connect such as
public class EFDbContext : DbContext
{
public DbSet<Product> Products
{
get;
set;
}
}
Now, you only need a connection string in your project's WebConfig file (not the webConfig in the Views folder). Add a connectionStrings section under the configuration node like this. NOTE: The class and the connection string must share an identical name - in this case, "EFDbContext".
<configuration>
<connectionStrings>
<add name="EFDbContext" connectionString="Data Source=SERVERNAME\;Initial Catalog=DATABASENAME;Persist Security Info=True;User ID=USERNAME;Password=PASSWORD"
providerName="System.Data.SqlClient"/>
</connectionStrings>
"SERVERNAME\" will connect you to the default installation. If you're looking for the default installation on your local machine, just enter your computer name and you're golden. If you prefer to use window authentication rather than SQL Server authentication, just substitute "Integrated Security=true" for the UserID/Pwd portion of the connection string. HTH
You can choose connection string using constructor as following way :
Public class EFDbContext : DbContext
{
public EFDbContext() : base("dbconninfo"){}
}
<configuration>
<connectionStrings>
<add name="dbconninfo" connectionString="Data Source=SERVERNAME\;Initial Catalog=DATABASENAME;Persist Security Info=True;User ID=USERNAME;Password=PASSWORD"
providerName="System.Data.SqlClient"/>
</connectionStrings>