| name | abp-efcore |
| description | ABP Framework v10.x (10.4/10.5) Entity Framework Core: AbpDbContext, ConfigureByConvention, AddAbpDbContext, repository (EfCoreRepository), migration, PostgreSQL/MySQL/SQLite/Oracle. Use when working with EF Core, DbContext, migrations, or repository implementation in ABP. |
ABP Framework โ Entity Framework Core
A guide to EF Core integration in ABP Framework v10.x (10.4/10.5). DbContext, repository, migration, eager/lazy loading.
Trigger
- "ABP EF Core"
- "ABP DbContext"
- "ABP migration"
- "ABP repository EF"
- "ABP ConfigureByConvention"
- "ABP WithDetails"
- "ABP DbSet"
DbContext
public class MyDbContext : AbpDbContext<MyDbContext>
{
public DbSet<Book> Books { get; set; }
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options) { }
}
Entity Mapping
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<Book>(b =>
{
b.ToTable("Books");
b.ConfigureByConvention();
b.Property(x => x.Name).IsRequired().HasMaxLength(128);
});
}
DbContext Registration
context.Services.AddAbpDbContext<MyDbContext>(options =>
{
options.AddDefaultRepositories();
});
DBMS Configuration
Configure<AbpDbContextOptions>(options =>
{
options.UseSqlServer();
options.Configure<MyOtherDbContext>(opts => opts.UseMySQL());
});
Custom Repository
public interface IBookRepository : IRepository<Book, Guid>
{
Task DeleteBooksByType(BookType type);
}
public class BookRepository : EfCoreRepository<BookStoreDbContext, Book, Guid>, IBookRepository
{
public BookRepository(IDbContextProvider<BookStoreDbContext> dbContextProvider)
: base(dbContextProvider) { }
public async Task DeleteBooksByType(BookType type)
{
var dbContext = await GetDbContextAsync();
await dbContext.Database.ExecuteSqlRawAsync($"DELETE FROM Books WHERE Type = {(int)type}");
}
}
Eager Loading
var queryable = await _orderRepository.WithDetailsAsync(x => x.Lines);
var orders = await AsyncExecuter.ToListAsync(queryable);
Object Extension Manager
ObjectExtensionManager.Instance
.MapEfCoreProperty<IdentityRole, string>("Title",
(entityBuilder, propertyBuilder) => propertyBuilder.HasMaxLength(64));
Choosing a DBMS
abp new Acme.BookStore -dbms PostgreSQL
abp new Acme.BookStore -dbms MySQL
abp new Acme.BookStore -dbms SQLite
abp new Acme.BookStore -dbms Oracle
PostgreSQL
[DependsOn(typeof(AbpEntityFrameworkCorePostgreSqlModule))]
Configure<AbpDbContextOptions>(options => options.UseNpgsql());
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
MySQL
Configure<AbpDbContextOptions>(options =>
{
options.Configure(ctx =>
{
ctx.DbContextOptions.UseMySql(ctx.ExistingConnection ?? ctx.ConnectionString);
});
});
Migrations
dotnet ef migrations add InitialCreate --project Acme.BookStore.EntityFrameworkCore --startup-project Acme.BookStore.DbMigrator
dotnet ef database update --project Acme.BookStore.EntityFrameworkCore --startup-project Acme.BookStore.DbMigrator
ReplaceDbContext
public interface IBookStoreDbContext : IEfCoreDbContext { DbSet<Book> Books { get; } }
context.Services.AddAbpDbContext<BookStoreDbContext>(options => options.AddDefaultRepositories<IBookStoreDbContext>());
[ReplaceDbContext(typeof(IBookStoreDbContext))]
public class UnifiedDbContext : AbpDbContext<UnifiedDbContext>, IBookStoreDbContext { }
Best Practices
- Always call
ConfigureByConvention()
- Keep the domain layer isolated from EF Core
- Use
IReadOnlyRepository for read-only queries
- Do eager loading with
WithDetailsAsync
v10.5+
- MySQL only:
ResourcePermissionGrant.ResourceName/ResourceKey max lengths shortened (utf8mb4 index limit). Regenerate/review fresh MySQL migrations after upgrading.
Related
DDD ยท MongoDB ยท Dependency Rules ยท Development Flow ยท Docs: https://abp.io/docs/latest/framework/data/entity-framework-core