Failed initial migration in Entity Framework Core on .NET 6 Isolated [duplicate] - entity-framework-core

.NET6 EFCore & Cosmos Migration issue. Need some help.
Hello folks. I am new in the world of .Net and I am facing an issue that Google has failed to help me solve. You're kind of my last regard.
So. I am trying to connect to an Azure Cosmos DB from my little HomeControlCenter Project using EFCore 6.0.3
The Error:
Unable to resolve service for type 'Microsoft.EntityFrameworkCore.Migrations.IMigrator'. This is often because no database provider has been configured for this DbContext. A provider can be configured by overriding the 'DbContext.OnConfiguring' method or by using 'AddDbContext' on the application service provider. If 'AddDbContext' is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext>
object in its constructor and passes it to the base constructor for DbContext.
My Program.cs:
builder.Services.AddDbContext<ControlCenterContext>(options =>
options.UseCosmos(builder.Configuration.GetConnectionString("DefaultConnection"), "ToDoList"));
My DbContext Impl:
public class ControlCenterContext : DbContext
{
public ControlCenterContext(DbContextOptions<ControlCenterContext> options) : base(options)
{
}
}
I also tried to use an override of OnConfiguring instead of the Program.cs line.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseCosmos(
"<AccountEndpoint>",
"<accountKey>",
databaseName: "ToDoList");
Nothing helped. When ever I run dotnet ef migrations add "initialSetup" I get the error mentioned above.
I read the error carefully and as you can see, I did apply all the necessary constructor params & other additions... I even tried to create a vanilla project and do the same all over again...

I couldn't find anything official from Microsoft, but the author of this blog states migrations using EF Core for CosmosDb are not supported: https://www.thereformedprogrammer.net/an-in-depth-study-of-cosmos-db-and-ef-core-3-0-database-provider/#1-no-migrations-can-cause-problems
This makes sense since CosmosDB is a document database, so it has no schema, it's just a bunch of JSON files. I ran into this issue when I wanted to use migrations to make seed data. The only solution I could think of was to create a separate project that uploaded the seed data with static values. But again, this was only seed data and not schema updates.

Related

Run different database types in different environments in dotnet core 2

I want to run a SQLite database in development and a SQLServer Express database in production.
We are using code first with database migrations.
How do I inject a different dbcontext in each environment?
How do I run migrations against a specific database. E.g. In development I'll want to run migrations against the SQLite database.
So I guess I found a nice way for you to do that. You can use the ConfigureDevelopmentServices startup convention to add your SQLSite DbContext. So, just as some basic example you would have:
// Production "like" ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
// Use Sql Server
services.AddDbContext<SchoolContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ProductionConnection")));
}
// Development ConfigureServices
public void ConfigureDevelopmentServices(IServiceCollection services)
{
// Use SQL Lite
services.AddDbContext<SchoolContext>(options =>
options.UseSqlite(Configuration.GetConnectionString("DevelopmentConnection")));
}
You can even go further and add a ConfigureStagingServices if you happen to have another different context for staging only. To avoid copy and pasting of common services, you could have a private method that register the common services and have the separate ones only with specific stuff.
Now for the migrations, I never tested this but, my best guess is if you have the correct dbContext and the correct connection string, the migrations will work fine. You just point to the EF project and run it.
For the official MS response, see Use SQLite for development, SQL Server for production

Stop a referenced dll from running migrations

I have a solution with a web application. This application uses Entity Framework and Code First. Then I have a second project, a console application. This console application shares the assembly that hold the migrations.
Is there a way to this console application that it should never run the Migrations? It could happen that this console application would contain a newer version which has not yet been deployed in the web application. I like to make sure there is no risk for the console to ruin the web application. Better to just have the console failing that updating the database.
Set the database initialiser to null in your DbContext constructor:
public class ConsoleContext : DbContext
{ public ConsoleContext()
: base("Name=" + Config.ConnectionStringName)
{
// Prevent attempt to initialize a database for this context
Database.SetInitializer<DtoContext>(null);
}
}
Alternatively,
in your web application:
protected void Application_Start()
{
Database.SetInitializer<MyDbContext>(
new MigrateDatabaseToLatestVersion<MyDbContext, Migrations.Configuration>());
}
and in your console application:
protected void Application_Start()
{
Database.SetInitializer<DtoContext>(null);
}
And, to be doubly certain, use two different database users. The web application will need db_datareader, db_datawriter and db_ddladmin roles if you're using Sql Server. The console application should only be in db_datareader and db_datawriter roles to prevent it changing the database schema
Easy) Yes, I have a good solution for that. in Nuget Console you have to provide the connection string and the target migration for the commands: Add-Migration/Update-Database.
Need Code) You can also do that programmatically by using DbMigrator.

Not able to update-database with Code First Entity Framework 6.1

In my project I am using code first and I was able to create my database and apply migrations to it via the nuget package manager console.
Now I added a second database context to my application and this context is not code first. this context is built on an existing database.
after adding the second context ... if I try to do a update-database, I get an error
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
System.NotSupportedException: Creating a DbModelBuilder or writing the EDMX from a DbContext created using Database First or Model First is not supported. EDMX can only be obtained from a Code First DbContext created without using an existing DbCompiledModel.
at System.Data.Entity.Infrastructure.EdmxWriter.WriteEdmx(DbContext context, XmlWriter writer)
at System.Data.Entity.Utilities.DbContextExtensions.<>c__DisplayClass1.<GetModel>b__0(XmlWriter w)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(Action`1 writeXml)
at System.Data.Entity.Utilities.DbContextExtensions.GetModel(DbContext context)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration, DbContext usersContext, DatabaseExistenceState existenceState)
at System.Data.Entity.Migrations.DbMigrator..ctor(DbMigrationsConfiguration configuration)
at System.Data.Entity.Migrations.Design.ToolingFacade.BaseRunner.GetMigrator()
at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
However, I ONLY want to apply migrations to my first context and want the second context to be left alone.
Solved the problem by directly specifying the Configuration type to be updated
update-database -ConfigurationTypeName Company.Project.Migrations.MySpecificConfiguration
This article helped a lot
http://www.dotnet-tricks.com/Tutorial/entityframework/2VOa140214-Entity-Framework-6-Code-First-Migrations-with-Multiple-Data-Contexts.html

Should i avoid multi datacontext and migration configuration on code-first project?

I am working on a ASP.NET MVC 5.1 project, I would using the ASP.NET Identity feature and code first.
By default, the ASP.NET Identity having their own datacontext (IdentityModels.cs) which inherit Microsoft.AspNet.Identity.EntityFramework.IdentityDbContext.
Because i afraid to influence the Identity model.
So i create another context inherrit DbContext , and create another migration configuration by following command:
enable-migrations -ContextTypeName PosApp.Models.OtherContext -MigrationsDirectory:OtherContextMigrations
And using specific configuration command line to update database:
Add-Migration -ConfigurationTypeName
PosApp.OtherContextMigrations.Configuration -Name GenDB Update-Database
-ConfigurationTypeName PosApp.OtherContextMigrations.Configuration
However, i found that it make the migration conflict between tables.
For example:
DataContext A and Configuration A:
Generate Table: Blog , Post , Comment
DataContext B and Configuration B:
Generate Table: User, but reference to Blog (1:N, that mean 1 user can have own multi blogs).
If i type command line - add-migration base on Config B.
The Blog table will be generate again, and conflict because the table exist on Config A.
Even i can override OnModelCreating() event and using modelBuilder.ignore<T> , but it resulting a mess.
So do i avoid multi config of migration?
Or any advantage on it?
You are on the right track using moddelBuilder.ignore. In your identityDbContext add:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<Blog>();
base.OnModelCreating(modelBuilder);
}
Then, to use your relationship from the User to the Blog, create a new data-context inheriting from IdentityDbContext and don't add a migration to it.

How to explicitly name the database when using Entity Framework Migrations 4.3

I've recently started using Entity Framework migrations and noticed that the database name is not pulling through for me when I run the Update-Database command.
My connectionstring is:
<connectionStrings>
<add name="DataContext" connectionString="Server=.\SQLEXPRESS;Initial Catalog=TestDB;Trusted_Connection=Yes;" providerName="System.Data.SqlClient" />
</connectionStrings>
The very first time I run Update-Database my database is created with the correct name TestDB. However, as soon as I make a change to one of my entities it will not update any longer for me unless I add a Start Up Project Name (I'm using a multi project solution):
Update-Database -StartUpProjectName "TestDB.Data"
This then makes another new database which migrations will always continue to use. I don't mind having to put in the StartUpProjectName command but is there a way to override the default name for the database this produces? It always creates the database as
TestDB.Data.DataContext
Is there a way to ensure that the database created when passing the StartUpProject name is just called TestDB or is this a limitation of using the StartUpProjectName setting?
As a note, I think the reason I need to specify the StartUpProjectName is that I have a multilayer project setup. The Migrations Configuration file is in my 'Data' project, the entities/models are in my 'Domain' project, etc. I also do not currently have any initialize options in my Global.asax.cs file as I would have used previously on code first ef 4.2. So in my project I just have a DataContext in my Data project and the Migrations Configuration in that project also.
EDIT:
Since I originally setup this question I stumbled onto the 'correct' way to name a database in a multiproject solution. While the answer below will work it does mean you are duplicating your web.config in another area which isn't an ideal solution. Instead you can just put the name into your DbContext by doing something like this (DataContext is just the name I used in my project):
public class DataContext : DbContext
{
public DataContext() : base("DatabaseNameHere")
{ }
public DbSet<Table1> Table1 { get; set; }
public DbSet<Table2> Table2 { get; set; }
public virtual void Commit()
{
base.SaveChanges();
}
}
Thanks,
Rich
You can avoid managing it in app.config by offering it as a parameter:
Update-Database -Verbose
-ConnectionString "CONNECTIONSTRING"
-ConnectionProviderName "System.Data.SqlClient"
-StartupProjectName WEBSITE_PROJECT -ProjectName MIGRATION_PROJECT
Easy-piezy, if you love to type endlessly.
When doing update-database you should specify the project that contains the migrations. Make sure that you have an app.config file in that project that contains the correct connection string.
When splitting up an application over several projects, the connection string used when running the app is the one of the project started. When migrating, the connection string used is the one of the project containing the migrations.
When I did a similar setup I had to add the connection string in two places. A bit awkward, but it works.
You can have your connection string stored in the web.config in your website project and the DBContext and migration files in another project and still share the same connection string. However you need to make sure that as well as setting the Data project (or whatever project has the DBContext etc. in it) as the default project for the Package Manager Console, you ALSO need to make sure that your website is set to the Default StartUp Project!!!
I cannot see this documented anywhere, but a frantic 24 hours of not being able to figure out why my migrations where suddenly being applied to a SQLExpress db, led me to this conclusion.
I tried with Latest EF5 from Nuget.
However Update-Database does not read the App.config from the project that contain the migrations (just like the answer 1 year ago) but it will only read *.config from start up project. It is great but I discover how Add-Migration and Update-Database find a suitable connection string here:
It trying to get "DefaultConnection" connection string first
Then it is trying to get the connection string name based on context class name. E.g. I have the MyContext class derived from DbContext so I can use the "MyContext" connection string name. Useful when I have multiple db connections.
If both the above connection string names are not found, it will fail and show no "DefaultConnection" connection string unless you supply the -ConnectionStringName parameter. See get-help Update-Database to view the help page in the Package Manager Console.
There is no retry or fallback attempt, so if the "DefaultConnection" contains a wrong connection string, it will simply show an error.
If both DefaultConnection and context name exist in the connection strings, DefaultConnection will take precedence.
I would prefer #2 become the first try because the name is more specific but the above steps is what EF5 Migrations do when trying to connect to the db.