У меня многоуровневое веб-приложение, в котором проект Infrastructure содержит только Identities, а Persistence содержит все другие объекты. Для постоянства мне удалось создать миграцию, но для инфраструктуры не удалось. Разница между этими двумя заключается в том, что сохраняемость наследует DbContext и Infrastrutcure ApiAuthorizationDbContext
Код ниже:
public class ApplicationDbContext : ApiAuthorizationDbContext<ApplicationUser>
{
public ApplicationDbContext(
DbContextOptions<ApplicationDbContext> options,
IOptions<OperationalStoreOptions> operationalStoreOptions) : base(options, operationalStoreOptions)
{
}
} public class IMSDbContext : DbContext, IIMSDbContext
{
private readonly ICurrentUserService _currentUserService;
private readonly IDateTime _dateTime;
public IMSDbContext(DbContextOptions<IMSDbContext> options) : base(options)
{
}
public IMSDbContext(DbContextOptions<IMSDbContext> options, ICurrentUserService currentUserService, IDateTime dateTime) : base(options)
{
_currentUserService = currentUserService;
_dateTime = dateTime;
}
public DbSet<ItemType> ItemTypes { get; set; }
public DbSet<Item> Items { get; set; }
public DbSet<Employee> Employees { get; set; }
public DbSet<ItemDetail> ItemDetails { get; set; }
public DbSet<Location> Locations { get; set; }
public DbSet<ItemImage> ItemImages { get; set; }
public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = new CancellationToken())
{
foreach (var entry in ChangeTracker.Entries<AuditableEntity>())
{
switch (entry.State)
{
case EntityState.Added:
entry.Entity.CreatedBy = _currentUserService.UserId;
entry.Entity.Created = _dateTime.Now;
break;
case EntityState.Modified:
entry.Entity.ModifiedBy = _currentUserService.UserId;
entry.Entity.Modified = _dateTime.Now;
break;
}
}
return base.SaveChangesAsync(cancellationToken);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.ApplyConfigurationsFromAssembly(typeof(IMSDbContext).Assembly);
}
}
Когда я запускаю добавочную миграцию -p Инфраструктура -c ApplicationDbContext из проекта Persistence, где установленEFCore.Design Получена следующая ошибка:
Невозможно создать объект типа 'ApplicationDbContext'. Для различных шаблонов, поддерживаемых во время разработки, см. https://go.microsoft.com/fwlink/?linkid=851728
Вот DI для инфраструктуры:
public static class DependencyInjection
{
public static IServiceCollection AddInfrastructure(this IServiceCollection services,
IConfiguration configuration, IWebHostEnvironment environment)
{
services.AddScoped<IUserManager, UserManagerService>();
services.AddTransient<INotificationService, NotificationService>();
services.AddTransient<IDateTime, MachineDateTime>();
services.AddDbContext<ApplicationDbContext>(
options => options.UseSqlServer(configuration.GetConnectionString("IMSDatabase")));
services.AddDefaultIdentity<ApplicationUser>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>();
services.AddAuthentication()
.AddIdentityServerJwt();
return services;
}
}
А вот и запуск из проекта WebAPI.
public class Startup
{
private IServiceCollection _services;
public Startup(IConfiguration configuration, IWebHostEnvironment environment)
{
Configuration = configuration;
Environment = environment;
}
public IConfiguration Configuration { get; }
public IWebHostEnvironment Environment { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddInfrastructure(Configuration, Environment);
services.AddPersistence(Configuration);
services.AddApplication();
services.AddControllers();
_services = services;
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
private void RegisteredServicesPage(IApplicationBuilder app)
{
app.Map("/services", builder => builder.Run(async context =>
{
var sb = new StringBuilder();
sb.Append("<h1>Registered Services</h1>");
sb.Append("<table><thead>");
sb.Append("<tr><th>Type</th><th>Lifetime</th><th>Instance</th></tr>");
sb.Append("</thead><tbody>");
foreach (var svc in _services)
{
sb.Append("<tr>");
sb.Append($"<td>{svc.ServiceType.FullName}</td>");
sb.Append($"<td>{svc.Lifetime}</td>");
sb.Append($"<td>{svc.ImplementationType?.FullName}</td>");
sb.Append("</tr>");
}
sb.Append("</tbody></table>");
await context.Response.WriteAsync(sb.ToString());
}));
}
}
Может кто-нибудь помочь мне понять, что я сделал не так? С уважением, Даниэль
ОБНОВЛЕНИЕ При запуске команды pmc:
add-migration Identity -c ApplicationDbContext -p Infrastructure -s Persistence -v
Using project 'src\Infrastructure'.
Using startup project 'src\Persistence'.
Build started...
Build succeeded.
C:\Program Files\dotnet\dotnet.exe exec --depsfile C:\Users\BoksanD\source\repos\IMS\Persistence\bin\Debug\netcoreapp3.0\IMS.Persistence.deps.json --additionalprobingpath C:\Users\BoksanD\.nuget\packages --additionalprobingpath C:\Microsoft\Xamarin\NuGet --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig C:\Users\BoksanD\source\repos\IMS\Persistence\bin\Debug\netcoreapp3.0\IMS.Persistence.runtimeconfig.json C:\Users\BoksanD\.nuget\packages\microsoft.entityframeworkcore.tools\3.0.0\tools\netcoreapp2.0\any\ef.dll migrations add Identity --json --context ApplicationDbContext --verbose --no-color --prefix-output --assembly C:\Users\BoksanD\source\repos\IMS\Persistence\bin\Debug\netcoreapp3.0\IMS.Infrastructure.dll --startup-assembly C:\Users\BoksanD\source\repos\IMS\Persistence\bin\Debug\netcoreapp3.0\IMS.Persistence.dll --project-dir C:\Users\BoksanD\source\repos\IMS\Infrastructure\ --language C# --working-dir C:\Users\BoksanD\source\repos\IMS --root-namespace IMS.Infrastructure
Using assembly 'IMS.Infrastructure'.
Using startup assembly 'IMS.Persistence'.
Using application base 'C:\Users\BoksanD\source\repos\IMS\Persistence\bin\Debug\netcoreapp3.0'.
Using working directory 'C:\Users\BoksanD\source\repos\IMS\Persistence'.
Using root namespace 'IMS.Infrastructure'.
Using project directory 'C:\Users\BoksanD\source\repos\IMS\Infrastructure\'.
Finding DbContext classes...
Finding IDesignTimeDbContextFactory implementations...
Found IDesignTimeDbContextFactory implementation 'IMSDbContextFactory'.
Found DbContext 'IMSDbContext'.
Finding application service provider...
Finding Microsoft.Extensions.Hosting service provider...
No static method 'CreateHostBuilder(string[])' was found on class 'Program'.
No application service provider was found.
Finding DbContext classes in the project...
Found DbContext 'ApplicationDbContext'.
Microsoft.EntityFrameworkCore.Design.OperationException: Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
---> System.MissingMethodException: No parameterless constructor defined for type 'IMS.Infrastructure.Identity.ApplicationDbContext'.
at System.RuntimeType.CreateInstanceDefaultCtorSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean fillCache)
at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, Boolean wrapExceptions)
at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions)
at System.Activator.CreateInstance(Type type)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_3.<FindContextTypes>b__13()
--- End of inner exception stack trace ---
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.<>c__DisplayClass13_3.<FindContextTypes>b__13()
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(Func`1 factory)
at Microsoft.EntityFrameworkCore.Design.Internal.DbContextOperations.CreateContext(String contextType)
at Microsoft.EntityFrameworkCore.Design.Internal.MigrationsOperations.AddMigration(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigrationImpl(String name, String outputDir, String contextType)
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.AddMigration.<>c__DisplayClass0_0.<.ctor>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.<>c__DisplayClass3_0`1.<Execute>b__0()
at Microsoft.EntityFrameworkCore.Design.OperationExecutor.OperationBase.Execute(Action action)
Unable to create an object of type 'ApplicationDbContext'. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
А вот Program.cs
namespace IMS.WebAPI
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var northwindContext = services.GetRequiredService<IMSDbContext>();
northwindContext.Database.Migrate();
var identityContext = services.GetRequiredService<ApplicationDbContext>();
identityContext.Database.Migrate();
}
catch (Exception ex)
{
var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while migrating or initializing the database.");
}
}
host.Run();
}
public static IWebHostBuilder CreateHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
var env = hostingContext.HostingEnvironment;
config.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
if (env.IsDevelopment())
{
var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName));
if (appAssembly != null)
{
config.AddUserSecrets(appAssembly, optional: true);
}
}
config.AddEnvironmentVariables();
if (args != null)
{
config.AddCommandLine(args);
}
})
.ConfigureLogging((hostingContext, logging) =>
{
logging.AddConfiguration(hostingContext.Configuration.GetSection("Logging"));
logging.AddConsole();
logging.AddDebug();
})
.UseStartup<Startup>();
}
}