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...
Related
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.
I have read many other post about fixing the issue for NullReferenceException when calling ConfigurationManager.ConnectionStrings as well as what to do when Unit Test is using machine.config rather than app.config but none have worked for me. Below is a list of approaches that I've tried and have been unsuccessful with so far.
Add Existing Item to unit test and reference the app.config for the project you are testing against
Copy the app.config from the targeted project and paste it in the unit test project
Ensure the bin folder of the unit test project is copying the appropriate config file
Set the properties for the unit test to copy to output as always
Below is a copy of my current config within the Unit Test project:
<configuration>
<appSettings>
<add key="Environment" value="Development" />
</appSettings>
<connectionStrings>
<add name="Connection.Development" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDB)\***;Initial Catalog=***;Persist Security Info=True;Integrated Security=True;Pooling=False" />
</connectionStrings>
</configuration>
I am expecting the following line of code to return Connection.Development connection string but instead I get the LocalSqlServer connection string from the machine.config consistently
string connectionString = ConfigurationManager.ConnectionStrings["Connection.Development"].ConnectionString;
I am using VS2017, running .Net Core 2.0, and trying to connect to local MS SQL Db within the application. If someone could tell me how they fixed this problem for their issue it would be greatly appreciated. If you know why, please pass that information along as well.
I'm on .NET 4.6.1, Visual Studio 2015, SQL Server Developer 2016. I want to specify my EF connection string in my main project's web.config, but I cannot for the life of me figure out how to reference that in my data access project. Every answer I can find says to do the same as in this one--that is, use this:
System.Configuration.ConfigurationManager
.ConnectionStrings["connectionStringName"].ConnectionString;
When I use that, however, the valid connection string isn't being passed. It's instead getting one that appears to be the default; the data source is being set to .\SQLEXPRESS when I have no string with that defined anywhere. Searching all files in the solution for SQLEXPRESS returns no results, so it's not hardcoded anywhere.
What is the correct way to pass my connection string from my main web.config (with the relevant transforms per build) to my data access project?
There is only one app.config / web.config that will be read from at run time and that is the config associated with the applications entry point. So if you have a web project and a referenced project that serves at the data access layer and you want to read a connection string from the config the web.config of the web project is used. The same is true for a windows application or wpf etc, only the applications main entry point's configuration will be used. Once your application is running you can reference that app.config / web.config from anywhere in your code though as you generally do this using string identifiers.
In other words if you have a project with your Data Access compiled to MyDA.dll and you app.config in that project that might be output to MyDA.dll.config (this does not happen by default) anything you have in MyDA.dll.config is ignored at runtime. The file will not be read from, only the web.config will be used OR the app.config of the .exe's entry point.
For Entity Framework's DbContext you can pass the name of the connection string directly to the constructor. You do not have to retrieve the connection string and pass it yourself. So give each connection a specific unique name in your web.config.
<connectionStrings>
<add name="ConnectionName1" connectionString="Data Source=(local);Database=YourDB;User Id=YourUser;Password=yourPassword" providerName="System.Data.SqlClient" />
<add name="ConnectionName2" connectionString="Data Source=(local);Database=YourDB2;User Id=YourUser2;Password=yourPassword2" providerName="System.Data.SqlClient" />
<!-- more here -->
</connectionStrings>
Then in your code you can create your Entity Framework's DbContext using that name.
var myEntities = new MyEntities("ConnectionName1"); // MyEntities is some class that derives from DbContext
In my past projects the DbContext I work with usually always maps to one database at run time. What I mean here is I would not use the same DbContext type multiple times pointing to different databases. In this case I hard code that name right into my DbContext type and make sure that my consuming applications have that connection name listed in the web.config or app.config respectively.
public class MyEntities : DbContext {
public MyEntities() : base("ConnectionName1") {}
}
// calling code now never has to know about the connection
using(var myEntities = new MyEntities()) { /* do something here */}
Alternatively if you really do want the complete connection element you can reference System.Configuration (add it to your project references in the project where you make the following call) and call it this way.
var connection = System.Configuration.ConfigurationManager.ConnectionStrings["ConnectionName1"];
var conString = connection.ConnectionString; // you can also get the provider
var myEntities = new MyEntities(conString);
I have not used this approach in a while but maybe there is a good reason to use it in your case.
The data source is being set to .\SQLEXPRESS when I have no string with that defined anywhere. Searching all files in the solution for SQLEXPRESS returns no results, so it's not hardcoded anywhere.
Its hardcoded in your machine config file. Simply add:
<clear />
Above your first connection string to remove it.
You could remove the .\SQLExpress connection string from line 126 in the machine.config, however IMHO play on the safe side and dont mess with machine config, preferring to use <clear /> instead.
Have you tried connection to the Server Explorer -> Data Connections and having the property auto generated? Next thing I would tried is adding an ADO.Net data model and pointing to the correct DB with the Access driver. It may be as simple as provider on the configuration string.
Here is a simplified example and/or proper way given by MSDN:
var connectionString = ConfigurationManager.ConnectionStrings["connectionStringName"].ConnectionString;
config file like the following:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name="connectionStringName" connectionString="Data Source=(LocalDB)\v11.0;Initial Catalog=DatabaseName;Integrated Security=True;Pooling=False" />
</connectionStrings>
</configuration>
Needed namespaces:
System.Configuration
From : https://msdn.microsoft.com/en-us/library/system.configuration.configurationmanager.connectionstrings(v=vs.110).aspx
As far as I remember, when using EF, it creates a connection string that matches the name of the context you defined, so, if your context is named MyContext then you should define a connection string with that name in your app/web.config. To save you the trouble of writing the EF connection string on your own (which is much longer than a regular ADO.Net connection string), just copy the one that was generate in the DLLs .config file.
Once you have that, you can use the configuration transformation functionality built into web projects, that allows you to change portions of the .config file depending on the current build configuration, for example:
web.config - Will hold the DEVELOPMENT connection string.
web.staging.config - will hold a replace transformation with the STAGING connection string.
web.release.config - will hold a replace transformation with the RELEASE connection string.
Hope it helps!
<configuration>
<connectionStrings>
<add name="CONNECTIONSTRINGNAME" connectionString="server=.; Database=YOURDATABASENAME;Integrated Security=true;" providerName="System.Data.SqlClient"/>
</connectionStrings>
</configuration>
change the capital letters with your own data
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.
Entity Framework doesn't seem to actually be reading connection strings from the Web.config.
I started a new project and created a context:
public class FooContext : DbContext
{
public FooContext() :
base("Foo")
{
}
// DbSets here
}
Then, I added a connection string to the projects 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="Foo" providerName="System.Data.SqlClient" connectionString="Data Source=Foo;Initial Catalog=Foo;Integrated Security=False;User Id=foo;Password=foo;MultipleActiveResultSets=True" />
</connectionStrings>
<appSettings>
...
I enabled migrations, generated an initial migration, and then attempted to update the database. After a while, the update fails saying that it couldn't connect to the database. So I pulled my project DLL into LINQPad and ran the following:
var context = new FooContext();
context.Database.Connection.ConnectionString.Dump();
And I get the following output:
Data Source=.\SQLEXPRESS;Initial Catalog=Foo;Integrated Security=True;MultipleActiveResultSets=True
It's trying to connect to LocalDB, completely ignoring my connection string. So I tried being more explicit in the context constructor, by using "name=Foo" instead of just "Foo".
public FooContext() :
base("name=Foo")
{
}
For what it's worth, I've never had to do this before. I've even got other projects in the same solution where the I've simply passed the connection string name and they've been working fine.
I jump back over to LINQPad and run the code again, and now I get an exception:
No connection string named 'Foo' could be found in the application config file.
I'm at a complete loss. I've set up projects like this 100s of times and never had any issues. Since it may be important, I'm running the latest Entity Framework, 6.1.3. Any ideas what could possibly be going on here?
I am assuming you are running this in Visual studio, make sure you are running your web project as a startup project to use web.config. If you are running another console or .tests project as startup, it will pick up their app.config files as config file.
Please remember that EntityFramework searches connection strings in the config of the assembly which runs the code. If you for instance execute your EF methods using test methods by unit test runner then EF will search it in your tests assembly, not in the place where EF methods are stored. I believe it may be your case.
By the way - in EntityFramework 5, when Edmx is created it automatically generates DbContext it uses name=ConnectionString, not only ConnectionString, so it's I think okay.