I am working on a project with ASP.NET CORE 1.0.0 and I am using EntityFrameworkCore. I have separate assemblies and my project structure looks like this:
Pr
All you have to do, is modify your ConfigureServices like this:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ProjectDbContext>(item => item.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection"),
b => b.MigrationsAssembly("Project.Api")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ProjectDbContext>()
.AddDefaultTokenProviders();
}
By Default VS will use the Assembly of the project where the DbContext is stored. The above change, just tells VS to use the assembly of your API project.
You will still need to set your API project as the default startup project, by right clicking it in the solution explorer and selecting Set as Startup Project
For all of you who have multiple startup projects.
Notice that you need to set your target project as startup project - Project.Api
(form the question example) should be the startup project.
Hope that will help someone :)
I have resolved it by adding below line in Startup.cs. Hope it will help you also. I have used Postgres you can use Sql Server instead of that
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
})
.AddSigningCredential(cert)
.AddCustomUserStore<IdentityServerConfigurationDbContext>()
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = builder =>
builder.UseNpgsql(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
});
The below command did the trick for me. I'm using VS Code and I run the following command:
SocialApp.Models> dotnet ef migrations add InitialMigartion --startup-project ../SocialApp.API
Courtesy: https://github.com/bricelam/Sample-SplitMigrations
This is for EF Core 3.x.
Based on this answer from Ehsan Mirsaeedi and this comment from Ales Potocnik Hahonina, I managed to make Add-Migration work too.
I use Identity Server 4 as a NuGet package and it has two DB contexts in the package. Here is the code for the class that implements the IDesignTimeDbContextFactory interface:
public class PersistedGrantDbContextFactory : IDesignTimeDbContextFactory<PersistedGrantDbContext>
{
public PersistedGrantDbContext CreateDbContext(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var dbContextBuilder = new DbContextOptionsBuilder<PersistedGrantDbContext>();
var connectionString = configuration.GetConnectionString("db");
dbContextBuilder.UseSqlServer(connectionString, b => b.MigrationsAssembly("DataSeeder"));
return new PersistedGrantDbContext(dbContextBuilder.Options, new OperationalStoreOptions() { ConfigureDbContext = b => b.UseSqlServer(connectionString) });
}
}
Compared to the answer of Ehsan Mirsaeedi I modified these: I added the MigrationsAssembly:
dbContextBuilder.UseSqlServer(connectionString, b => b.MigrationsAssembly("DataSeeder"));
Where the "DataSeeder" is the name of my startup project for seeding and for migrations.
I added an options object with ConfigureDbContext property set to the connection string:
return new PersistedGrantDbContext(dbContextBuilder.Options, new OperationalStoreOptions() { ConfigureDbContext = b => b.UseSqlServer(connectionString) });
It is now usable like this: 'Add-Migration -Context PersistedGrantDbContext
At this point, when a migration has been created, one can create a service for this in a migration project having a method like this:
public async Task DoFullMigrationAsync()
{
using (var scope = _serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
{
var persistedGrantDbContextFactory = new PersistedGrantDbContextFactory();
PersistedGrantDbContext persistedGrantDbContext = persistedGrantDbContextFactory.CreateDbContext(null);
await persistedGrantDbContext.Database.MigrateAsync();
// Additional migrations
...
}
}
I hope I helped someone.
Cheers,
Tom
I was facing similar issue, though answers seems straight forward somehow they didn't work. My Answer is similar to @Ehsan Mirsaeedi, with small change in DbContextFactory class. Instead of Adding migration assembly name in Startup class of API, I have mentioned in DbContextFactory class which is part of Data project(class library).
public class DbContextFactory : IDesignTimeDbContextFactory<KuchidDbContext>
{
public KuchidDbContext CreateDbContext(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var dbContextBuilder = new DbContextOptionsBuilder<KuchidDbContext>();
var connectionString = configuration.GetConnectionString("connectionString");
var migrationAssemblyName= configuration.GetConnectionString("migrationAssemblyName");
dbContextBuilder.UseSqlServer(connectionString, o => o.MigrationAssembly(migrationAssemblyName));
return new KuchidDbContext(dbContextBuilder.Options);
}
}
You would need 'Microsoft.Extensions.Configuration' and 'Microsoft.Extensions.Configuration.Json' for SetBasePath & AddJsonFile extensions to work.
Note: I feel this is just a work around. It should pickup the DbContextOptions from the startup class somehow it is not. I guess there is definitely some wiring issue.