Reputation: 307
I am trying to implement CA in an ASP.NET Core Web API. Right now I have the presentation, infrastructure and application all set up, but when I tried Updating the Database with the DbContext Entities I have set up, I was met with this error:
Unable to create a 'DbContext' of type 'AppDbContext'. The exception 'The method or operation is not implemented.' was thrown while attempting to create an instance. For the different patterns supported at design time, see https://go.microsoft.com/fwlink/?linkid=851728
After some research I realized it was becouse even though within my .Presentation layer I was in fact configuring and referencing the AppDbContext within the .Infrastructure layer. It wasn't enough I needed to initialize it via a ContextFactory.
After a little bit more research I found a ContextFactory Model within the Ultimate ASP.NET Core book.
public class AppContextFactory : IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlServer(configuration.GetConnectionString("Default"),
b => b.MigrationsAssembly("Clean.Presentation"));
return new AppDbContext(builder.Options);
}
}
After implementing said ContextFactory within my Presentation layer I was surprised to see that the error when trying to update the Database kept appearing.
These are all of the relevant parts:
This is my AppDbContext Within my Infrastructure Layer:
public AppDbContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.ApplyConfiguration(new PersonaConfiguration());
//Initial Seeder
......
base.OnModelCreating(builder);
}
public DbSet<Usuario> Usuarios { get; set; } = null!;
public DbSet<Cargo> Cargos { get; set; } = null!;
public DbSet<CargoAsignado> CargoAsignados { get; set; } = null!;
public DbSet<Persona> Personas { get; set; } = null!;
}
As you can see pretty basic stuff.
This is The configuration within my Services Extensions in my .Presentation layer:
public static void ConfigureDbContext(this IServiceCollection services, IConfiguration config)
{
services.AddDbContext<AppDbContext>(options =>
{
options.UseSqlServer(config.GetConnectionString("Default"));
});
}
And its implementation within the Pipeline:
builder.Services.ConfigureDbContext(builder.Configuration);
Upvotes: 0
Views: 55
Reputation: 28267
After researching your application, I found your dbcontext contains this error:
Unable to create a 'DbContext' of type 'AppDbContext'. The exception 'Both relationships between 'Usuario.Persona' and 'PersonaBase' and between 'Usuario' and 'Persona.Usuario' could use {'PersonaId'} as the foreign key. To resolve this, configure the foreign key properties explicitly in 'OnModelCreating' on at least one of the relationships.' was thrown while attempting to create an instance.
This error is related with the Usuario model.
Inside the Usuario model, it contains two relationship for the PersonaBase. PersonaId AND Persona.
You should remove the public int PersonaId { get; set; }
and then the application dbcontext will work well.
public class Usuario : IdentityUser
{
public DateOnly FechaCreacion { get; set; } = DateOnly.FromDateTime(DateTime.UtcNow);
public int PersonaId { get; set; }
[ForeignKey("PersonaId")]
public PersonaBase Persona { get; set; } = null!;
}
The dbcontext should like below:
public class AppDbContext : IdentityDbContext<Usuario>
{
public AppDbContext(DbContextOptions options) : base(options) { }
protected override void OnModelCreating(ModelBuilder builder)
{
builder.ApplyConfiguration(new PersonaConfiguration());
var newPersona = new Persona
{
Id=1,
Nombre = "Ismael",
ApellidoPaterno = "Moron",
ApellidoMaterno = "Pedraza",
Carnet = "12597382",
Telefono = "75526864"
};
builder.Entity<Persona>().HasData(newPersona);
var passwordHasher = new PasswordHasher<string>();
var newUsuario = new Usuario
{
UserName = "ismael",
PasswordHash = passwordHasher.HashPassword(null!, "123456"),
PersonaId = newPersona.Id
};
builder.Entity<Usuario>().HasData(newUsuario);
var newCargo = new Cargo
{
Name = "Sudo",
NormalizedName = "SUDO"
};
builder.Entity<Cargo>().HasData(newCargo);
var newCargoAsignado = new CargoAsignado
{
UserId = newUsuario.Id,
RoleId = newCargo.Id
};
builder.Entity<CargoAsignado>().HasData(newCargoAsignado);
base.OnModelCreating(builder);
}
public DbSet<Usuario> Usuarios { get; set; } = null!;
public DbSet<Cargo> Cargos { get; set; } = null!;
public DbSet<CargoAsignado> CargoAsignados { get; set; } = null!;
public DbSet<Persona> Personas { get; set; } = null!;
}
Upvotes: 0