Code first update-database uses localdb connection string which is not specified - c#

Visual Studio 2019, C#
I'm working on my first code first implementation.
I built out a data access layer which works great. I then went to add/test out a data migration.
I created a migration file then went to the package manager console and ran this:
update-database
after a long pause I saw a message that stated:
Target database is: 'OMDB' (DataSource: (localdb)\mssqllocaldb, Provider: System.Data.SqlClient, Origin: Convention).
OMDB is my model. However, I'm not pointing it to localDB in my app.config, I'm pointing to sqlexpress:
….
<connectionStrings>
<add name="OMDB" connectionString="data source=.\SQLEXPRESS;initial catalog=MyDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value ="data source=.\SQLEXPRESS;initial catalog=MyDB;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework"/>
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
…
In order to get the data access layer built out, I had to add an override to the class constructor to load the connection string:
public OMDB(string szConnectionString) : base(szConnectionString)
{ }
But I don't think that has anything to do with my issue...
I have the default project set to the data access layer project (DAL), I also tried forcing that on the update-database line:
update-database -Verbose -ProjectName DAL
I did a global search for localDB in my solution and it came up with no hits so I have no idea where it's getting the idea of it using the localdb for the source...?
Any suggestions on where it's pulling up the localDB for this connection?

I managed to fix the issue by following steps.
Set your website project(where the web.config has the connectionStrings) as Default/Startup project in Visual Studio
Make sure the connectionString points to the actual db instance
Run Enable-Migrations or Enable-Migrations -Force in Package Manager Console depending on your need
You should get a message like below upon successful creation of the InitialModel:
Detected database created with a database initializer. Scaffolded
migration '202102050903200_InitialCreate' corresponding to existing
database. To use an automatic migration instead, delete the Migrations
folder and re-run Enable-Migrations specifying the
-EnableAutomaticMigrations parameter.

Ok, this one really made me burn some time.... I figured out what was causing it and also a workaround at least for now.
I have a project in the solution which is my data access layer. Even though I had that project selected in the package manager console, it created a blank app config at the top level. Since that app.config did not have the connection string tags in it, it was defaulting to localdb and eventually erroring out.
So to get around that, I copied the connection string from the data access library project app.config to the master project app.config and everything started working. Not sure why it wanted to go to the main project file but it was... I'll have to come back to this later but it's working for now.

Related

Visual Studio 2017 not showing MySQL in connection list

I am using "Visual Studio 2017 Professional". I can not get a project to recognize that MySQL is an available DB option. MySQL does not show up in the list of possible connections when I create a new model. I know that there are tons of SO questions and other web pages on this topic because I have tried a lot of the suggestions. Each is subtlety different in cause and solution. None of the solutions seem to work for me.
I have tried the following with VS 2017 and 2015 with the same results. I have older versions of VS available but it didn't seem worthwhile to march that far back. I have also tried installing the latest and older versions of MySQL both with the "Community Installer" and the standalone msi's when necessary. I went back to the "latest" pre-6.10 version of MySQL.
To begin, this saga started last week when I noticed that nuget had MySQL package updates available. I applied them and then went to upgrade the installed MySQL componants with the Community Installer. The nuget changes did apply. The Community Installer could not uninstall MySQL for VS though. The system installer could not uninstall it. Rebooting and power-cycling did nothing.
On the advice of our local tech support folks I used a third party uninstaller that turned out to be more aggressive than we imagined. It seems to have randomly stommped across the registry erasing whatever it found. Long story short(er), I ended up having my machine reimaged. So, I have a fresh windows install.
Given the fresh Win10 platform, I installed the various things I normally use including the VS versions I typically use. I installed the latest Community MySQL installer. I did a "custom" MySQL install because I don't need a server on this device or fabric or many other things.
I finished the basic reinstall of everything then rebooted just to be sure. I started VS 2017 and created a new web app with the latest available version of .Net (4.6.1). I applied nuget updates and added EntityFramework and MySQL.Data. I then tried to create a new "code first" model.
I can get to the point where I am asked to create a connection. When I click the button the list of available DB providers only shows MS SQL.
I have seen the articles that say to add lines to Web.config and I have seen the MySQL .Net Connector docs that say the same things. I can see the MySQL entries in Web.config but they do not show up when creating a connection.
An oddity is that I can go to Tools -> Connect to Database and see EVERY DB type my machine knows about including MySQL. I can create the connection string and it works. I can see the DB in "Server Explorer` but that doesn't make it available to code.
Ok, I have followed the above steps over and over including downgrading the version of EntityFramework as well as the MySQL version.
My most recent attempt has me back to the latest version of VS and MySQL. The relevant (I think) section of the Web.config file follow. Note the defaultConnectionFactory entry is LocalDbConnectionFactory. I have changed that to SqlConnectionFactory but it has not made a difference. I have also changed the order of the providers and the order of the major blocks.
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="mssqllocaldb" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient"
type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="MySql.Data.MySqlClient"
type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.10.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d">
</provider>
</providers>
</entityFramework>
<system.data>
<DbProviderFactories>
<remove invariant="MySql.Data.MySqlClient" />
<add description=".Net Framework Data Provider for MySQL" invariant="MySql.Data.MySqlClient"
name="MySQL Data Provider"
type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.10.6.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</DbProviderFactories>
</system.data>
Edit
My current impression is that VS 2017 is an unusable mess masquerading as a released, salable product. I have returned to 2015.
I have come closer to getting this to work in 2015. I have the latest MySQL items for VS and .Net installed. I have downgraded the nuget EF package to 6.0 and the MySql packages to 6.8.8.
In, what I am now calling, "the good old days" I could add a new model to an MVC project by selecting the Models folder; selecting "Add New Item"; choosing ADO.Net model; select a connection option (MySQL); enter the connection info; choose DB First or Code First and wait for the scaffolding fun to finish.
Now, I have to first go to Tools -> Connect to Database and create a conenction to a MySql DB. If I do not do this I will not see MySQL in the list of possible connections later. I then clean and build the project. Next i try to create the model as above. Noe I can see the MySQL connection option and I can enter the DB creds and test the connection.
The next step is to choose DB First or Code First. In either case, clicking the "next" button flashes a blank pop-up that then vanishes. No errors are shown and no connection is made.
It was never this hard in the past.
I have tried a lot of different MySQL and EF versions on 2015 and 2017 at this point. If there is a magic combo please tell me.
I have been fighting this fight for two weeks. I FINALLY found a combo of versions that works for me. The following was applied to a pristine re-image of my Win10 desktop two weeks ago. All patches were applied to system software before starting to deal with MySql.
Just this morning I re-read the post in this thread (MySql Forums): https://forums.mysql.com/read.php?174,659102,660369#msg-660369
I thought that I had tried those suggestions before but I must have messed up one of the versions. I think that poster's basic strategy is sound. In my case I uninstalled all local MySql parts and the installer.
I downloaded MySQL for Visual Studio - the Latest Development version (2.0.5 msi as of this writing) and installed that.
I found the OLD versions of the .Net Connector and installed 6.9.11
In VS 2017 I created a dummy project using .Net 4.6.1.
I applied pending VS updates.
I built the project.
I went to "Project -> Manage Nuget Packages" and installed / downgraded EntityFramework to 6.0.
I installed MySql.Data, MySql.Data.Entity and MySql.Web all at version 6.9.11
I cleaned and built the project then tried to add a new "Code First" model from a MySql DB... IT WORKED!
Thank you 7 Reeds for coming back with an answer. It led me to get it working, although I did it slightly differently.
In VS 2017 to connect to MySQL 5.6:
Uninstall any MySQL products from the machine
Set Target framework to .NET Framework 4.5.2
Uninstall EntityFramework and any MySQL packages in Nuget
Install MySql.Data.Entity (6.10.7)
It will also install the needed versions of the Nuget packages MySql.Data (6.10.7), EntityFramework (6.1.3), and BouncyCastle (1.8.3.1).
The MySql.Data.Entity package says it depends of Google.Protobuf, but it didn't install it and it works fine for me.
It added References in my project to BouncyCastle.Crypto (1.8.3.0), EntityFramework (6.0.0.0), MySQL.Data (6.10.7.0), and MySql.Data.Entity.EF6 (6.10.7.0).
Close Visual studio
Install 'MySQL for Visual Studio' (1.2.8)
Install 'Connector/NET' (6.10.7)
Delete the bin and obj folders
Open Visual Studio and Rebuild Solution
Add New Item > ADO.NET Entity Data Model > Now you're in the wizard
Select EF Designer from database
On the next screen ('Entity Data Model Wizard'), click New Connection...
On the 'Connection Properties' screen click the Change... button for the 'Data source'
You should be able to select the MySQL Database as the 'Data source'
The 'Data provider' should auto-populate with .NET Framework Data Provider for MySQL
Yay! Continue on like you normally would
For posterity, here's the app.config for my WPF application:
<?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" />
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --></configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
<parameters>
<parameter value="v13.0" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
<provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.Entity.EF6, Version=6.10.7.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" />
</providers>
</entityFramework>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="MySql.Data" publicKeyToken="c5687fc88969c44d" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.10.7.0" newVersion="6.10.7.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<connectionStrings>
<add name="MyDB" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=MySql.Data.MySqlClient;provider connection string="server=my.example.com;user id=NotMyRealUserID;password=NotMyRealPassword;persistsecurityinfo=True;database=MyDatabase"" providerName="System.Data.EntityClient" />
</connectionStrings>
</configuration>
I'm not sure what created this, but I have a 'User variable' in my 'Environment Variables' named MYSQLCONNECTOR_ASSEMBLIESPATH with value C:\Program Files (x86)\MySQL\MySQL Connector Net 6.10.7\Assemblies\v4.5.2
At appsettings.json:
"ConnectionStrings": { "DefaultConnection": "Server=localhost;database=MusicStoreDB;user id=root;Charset=utf8;" },
At ConfigureServices() in Startup.cs :
using Microsoft.EntityFrameworkCore; using MySql.Data.MySqlClient; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection;
... services.AddDbContext(options => options.UseMySQL(Configuration.GetConnectionString("DefaultConnection")));
Note: Change to:
UseMysql <-------------- When using Pompelo EntityFrameworkCore

Entity Framework targetting wrong database. (WPF)

While this wpf project runs very stabil for the past 2 years, i now get a EF problem stating "CREATE DATABASE permission denied in database 'master'."
All the migrations are in the _MigrationHistory table:
and nothing has changed from the config.
The app.config:
<connectionStrings>
<add name="DataContext" providerName="System.Data.SqlClient" connectionString="Server=********.com;Database=******;Integrated Security=False;Initial Catalog=*******;User ID=*******;Password=********" />
</connectionStrings>
the last action was a publish to a click once folder online.
I allready reinstalled EF 6.1.3 => no success
Please help we with debugging this issue, i don't know where to look first...
a simple get-migrations doesn't see the migrations.
PM> Get-Migrations
Retrieving migrations that have been applied to the target database.
No migrations have been applied to the target database.
PM>

.mdf file missing under the App_Data folder in ASP.NET MVC

I was following the tutorial on creating the Code First Entity Framework model on Asp.NET MVC Application from this tutorial.
As I proceeded, a file with the .mdf extension should have been generated under the App_Data folder in my project (in the solution explorer section). Currently this folder is empty.
I have tried building the project and cleaning it. Moreover I have enabled Show All Files option in the folder. I even did a refresh. The Entity Framework works just fine and is able to connect and retrieve from the database. However the App_Data folder is empty.
Here is are my connection strings:
<connectionStrings>
<add name="DefaultConnection" connectionString="Data Source=(LocalDb)\v11.0;AttachDbFilename=|DataDirectory|\aspnet-UsingEntityFramework-20161002112829.mdf;Initial Catalog=aspnet-UsingEntityFramework-20161002112829;Integrated Security=True"
providerName="System.Data.SqlClient" />
<add name="MovieDBContext" connectionString="Data Source=tcp:xxxxxxxxxx.net;Initial Catalog=xxxxx;User ID=xxxxx;Password=xxxxxx;" providerName="System.Data.SqlClient"/>
</connectionStrings>
Check your web.config and notice the connectionString and see the data source, maybe it is creating it under your SQL Server not inside the App_Data
The MDF File will be created when the database is created, and since this is a code first, the database will not be created unless you run the application and start connecting to the database, EF will create the database if it doesn't exist and will compare the schema to the schema in the Migrations folder and it will update the database if it is not up to date.
You can also open Nu Get Package Manager and run the command Update-Database to create and update the database.

Connection String in Unit Test App.Config is ignored: SQLExpress gets set to LocalDB

I have a load of unit tests that were running fine in Visual Studio 2013. I dont know if it is related, but I can't think of what else might have changed. I have moved my project to VS2015.
Now whenever I run my unit tests, all the tests that use a data context fail with an error indicating they are trying to use (localdb)\V11.0 and integrated security to access the database.
However, my development database is on .\sqlexpress and has a SQL login.
I've been through every config file, including the app.config in the unit test project, and they all specify the correct database. If I debug step through the code I can reach the line where the data context is created and inspect its properties and see the connection string is wrong, but I can't see where it is coming from.
Here's the relevant bit of my test project's app.config file:
<?xml version="1.0" encoding="utf-8"?>
<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="speedEntitiesDev" connectionString="metadata=res://*/mydb.csdl|res://*/mydb.ssdl|res://*/mydb.msl;provider=System.Data.SqlClient;provider connection string="Server=.\sqlexpress;Database=thedatabase;User ID=theuser;Password=thepassword;Connection Timeout=30;MultipleActiveResultSets=True"" providerName="System.Data.EntityClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework">
<parameters>
<parameter value="Server=.\sqlexpress;Database=thedatabase;User ID=theuser;Password=thepassword;Connection Timeout=30;MultipleActiveResultSets=True" />
</parameters>
</defaultConnectionFactory>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
When I step into the unit test this is what the property inspector says is the value of the connection string is:
"Data Source=(localdb)\\v11.0;Initial Catalog=thedatabase;Integrated Security=True"
Note that the database name is correct, but everything else is wrong.
I did previously have a database hosted locally in localdb but after upgrading my development computer I stopped using it.
UPDATE:
I've discovered that if I rename the connection in the above file, then this breaks the test in a different way. Then I get an error that the connection string is not found:
System.InvalidOperationException: No connection string named 'speedEntitiesDev' could be found in the application config file..
Other changes to the connection string also have an effect (like if I change the database name, the connection goes to the new database name, and uses the login and password I supply.)
System.Data.Entity.Core.EntityException: The underlying provider failed on Open. ---> System.Data.SqlClient.SqlException: Cannot open database "thedatabase123" requested by the login. The login failed. Login failed for user 'theuser'..
When I set the connection string back to "thedatabase" it resets to using localdb and integrated security. It's like it's got an alias going or something.
After diving through the code for a few days, I noticed that in one older library referenced by every class tested by every failing test, there was a data update written as:
dc.SubmitChanges();
and it hit me, this class was using LINQ to Sql instead of Entity Framework. Somehow the class using LINQ to Sql was altering the connection string and defaulting to (localdb) which was what we were using when that library was written.
I changed the class to use Entity Framework instead and suddenly all my tests started respecting the connection string again.
This was weird because
The old referenced library didn't actually do any data updates any more (the data update code in it was legacy and long since placed elsewhere)
The old library didn't even have a valid reference to the data class that supplied its connection string
Despite this, just referencing the old library via the unit tests caused connection string weirdness.

Running Code First Migrations manually through migrate.exe

I am currently trying to get my migrations running through command line using the migrate.exe tool.
My project structure is as follows:
MyProject.WebAPI - my API project which accesses method in
Repositories
MyProject.Repositories - project responsible for all DB work,
including where the migration files are stored, context is configured, and Configuration class is held
Migrations work fine when running the WebAPI project as the DB initializer is set up there in the Application_Start as follows:
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, MyProject.Repositories.Migrations.Configuration>());
The reason for wanting to not do this anymore, is for when I am installing the code to a machine. I am aiming to get the database initialized at install time, so need to be able to run migrations from command line. To start to do this, I have got a copy of migrate.exe in the bin directory of the WebApi project, as well as the MyProject.Repositories.dll.
I want to therefore be able to use the web.config file in the WebApi project to configure up and run the initializer. The entity framework portion of this looks as follows:
<configuration>
....
<connectionStrings>
<add name="MyConnectionString" connectionString="..." providerName="System.Data.SqlClient" />
</connectionStrings>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<contexts>
<context type="Repositories.MyContext, MyProject.Repositories">
<databaseInitializer type="System.Data.Entity.MigrateDatabaseToLatestVersion`2[[Repositories.MyContext, MyProject.Repositories], [Repositories.Configuration, MyProject.Repositories]], EntityFramework">
</databaseInitializer>
</context>
</contexts>
</entityFramework>
</configuration>
And I am running migrate.exe as follows:
migrate.exe MyProject.Repositories.dll /startUpDirectory:"%current%" /connectionStringName:MyConnecitonString /startUpConfigurationFile:"%parent%\web.config"
current and parent are just variables set in a batch file.
When this set up is run, I get the following error:
ERROR: Failed to set database initializer of type 'System.Data.Entity.MigrateDatabaseToLatestVersion`2[[MyProject.CampaignManagerContext, MyProject.Repositories], [Repositories.Configuration, MyProject.Repositories]], EntityFramework'
for DbContext type 'Repositories.MyContext, MyProject.Repositories' specified in the application configuration. See inner exception for details.
Is this possible to do between two projects, or would I have to run this on the actual Repositories project itself, using its own app.config?
EDIT:
I have been working more on this, and have changed my call to migrate to just:
migrate.exe MyProject.Repositories.dll /connectionString:MyConnectionString /connectionProviderName:System.Data.SqlClient
This gives me an error of:
ERROR: Format of the initialization string does not conform to specification starting at index 0.
Looks like it is getting closer to working...

Categories