Skip to main content

abp-ef-core

ABP Entity Framework Core - DbContext, entity configuration, EfCoreRepository implementation, migrations (dotnet ef migrations add), data seeding. Use when working in EntityFrameworkCore projects, adding migrations, or implementing EF Core repositories.

Quellinformationen

Repository
abpframework/abp
Letzte Quellaktivität
22. März 2026 um 17:13
Erkannte Sprache von SKILL.md
Englisch
Sterne
14.446
Forks
3.720

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
abp-ef-core
description
ABP Entity Framework Core - DbContext, entity configuration, EfCoreRepository implementation, migrations (dotnet ef migrations add), data seeding. Use when working in EntityFrameworkCore projects, adding migrations, or implementing EF Core repositories.
# ABP Entity Framework Core > **Docs**: https://abp.io/docs/latest/framework/data/entity-framework-core ## Never Do | Don't | Do Instead | |-------|-----------| | Skip `b.ConfigureByConvention()` | Always call it first in entity config | | `AddDefaultRepositories(includeAllEntities: true)` | Use `AddDefaultRepositories()` only for aggregate roots | | Inject `DbContext` in application/domain services | Use `IRepository<T>` or custom repository interface | | Use `DbContext` directly outside the EF Core project | Access via `GetDbContextAsync()` inside repository only | ## DbContext Configuration ```csharp [ConnectionStringName("Default")] public class MyProjectDbContext : AbpDbContext<MyProjectDbContext> { public DbSet<Book> Books { get; set; } public DbSet<Author> Authors { get; set; } public MyProjectDbContext(DbContextOptions<MyProjectDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // Configure all entities builder.ConfigureMyProject(); } } ``` ## Entity Configuration ```csharp public static class MyProjectDbContextModelCreatingExtensions { public static void ConfigureMyProject(this ModelBuilder builder) { Check.NotNull(builder, nameof(builder)); builder.Entity<Book>(b => { b.ToTable(MyProjectConsts.DbTablePrefix + "Books", MyProjectConsts.DbSchema); b.ConfigureByConvention(); // ABP conventions (audit, soft-delete, etc.) // Property configurations b.Property(x => x.Name) .IsRequired() .HasMaxLength(BookConsts.MaxNameLength); b.Property(x => x.Price) .HasColumnType("decimal(18,2)"); // Indexes b.HasIndex(x => x.Name); // Relationships b.HasOne<Author>() .WithMany() .HasForeignKey(x => x.AuthorId) .OnDelete(DeleteBehavior.Restrict); }); } } ``` ## Repository Implementation ```csharp public class BookRepository : EfCoreRepository<MyProjectDbContext, Book, Guid>, IBookRepository { public BookRepository(IDbContextProvider<MyProjectDbContext> dbContextProvider) : base(dbContextProvider) { } public async Task<Book> FindByNameAsync( string name, bool includeDetails = true, CancellationToken cancellationToken = default) { var dbSet = await GetDbSetAsync(); return await dbSet .IncludeDetails(includeDetails) .FirstOrDefaultAsync( b => b.Name == name, GetCancellationToken(cancellationToken)); } public async Task<List<Book>> GetListByAuthorAsync( Guid authorId, bool includeDetails = false, CancellationToken cancellationToken = default) { var dbSet = await GetDbSetAsync(); return await dbSet .IncludeDetails(includeDetails) .Where(b => b.AuthorId == authorId) .ToListAsync(GetCancellationToken(cancellationToken)); } public override async Task<IQueryable<Book>> WithDetailsAsync() { return (await GetQueryableAsync()) .Include(b => b.Reviews); } } ``` ## Extension Method for Include ```csharp public static class BookEfCoreQueryableExtensions { public static IQueryable<Book> IncludeDetails( this IQueryable<Book> queryable, bool include = true) { if (!include) { return queryable; } return queryable .Include(b => b.Reviews); } } ``` ## Migration Commands ```bash # Navigate to EF Core project cd src/MyProject.EntityFrameworkCore # Add migration dotnet ef migrations add MigrationName # Apply migration (choose one): dotnet run --project ../MyProject.DbMigrator # Recommended - also seeds data dotnet ef database update # EF Core command only # Remove last migration (if not applied) dotnet ef migrations remove # Generate SQL script dotnet ef migrations script ``` > **Note**: ABP templates include `IDesignTimeDbContextFactory` in the EF Core project, so `-s` (startup project) parameter is not needed. ## Module Configuration ```csharp [DependsOn(typeof(AbpEntityFrameworkCoreModule))] public class MyProjectEntityFrameworkCoreModule : AbpModule { public override void ConfigureServices(ServiceConfigurationContext context) { context.Services.AddAbpDbContext<MyProjectDbContext>(options => { // Add default repositories for aggregate roots only (DDD best practice) options.AddDefaultRepositories(); // ⚠️ Avoid includeAllEntities: true - it creates repositories for child entities, // allowing them to be modified without going through the aggregate root, // which breaks data consistency }); Configure<AbpDbContextOptions>(options => { options.UseSqlServer(); // or UseNpgsql(), UseMySql(), etc. }); } } ``` ## Best Practices ### Repositories for Aggregate Roots Only Don't use `includeAllEntities: true` in `AddDefaultRepositories()`. This creates repositories for child entities, allowing direct modification without going through the aggregate root - breaking DDD data consistency rules. ```csharp // ✅ Correct - Only aggregate roots get repositories options.AddDefaultRepositories(); // ❌ Avoid - Creates repositories for ALL entities including child entities options.AddDefaultRepositories(includeAllEntities: true); ``` ### Always Call ConfigureByConvention ```csharp builder.Entity<MyEntity>(b => { b.ConfigureByConvention(); // Don't forget this! // Other configurations... }); ``` ### Use Table Prefix ```csharp public static class MyProjectConsts { public const string DbTablePrefix = "App"; public const string DbSchema = null; // Or "myschema" } ``` ### Performance Tips - Add explicit indexes for frequently queried fields - Use `AsNoTracking()` for read-only queries - Avoid N+1 queries with `.Include()` or specifications - ABP handles cancellation automatically; use `GetCancellationToken(cancellationToken)` only in custom repository methods - Consider query splitting for complex queries with multiple collections ### Accessing Raw DbContext ```csharp public async Task CustomOperationAsync() { var dbContext = await GetDbContextAsync(); // Raw SQL await dbContext.Database.ExecuteSqlRawAsync( "UPDATE Books SET IsPublished = 1 WHERE AuthorId = {0}", authorId ); } ``` ## Data Seeding ```csharp public class MyProjectDataSeedContributor : IDataSeedContributor, ITransientDependency { private readonly IRepository<Book, Guid> _bookRepository; private readonly IGuidGenerator _guidGenerator; public async Task SeedAsync(DataSeedContext context) { if (await _bookRepository.GetCountAsync() > 0) { return; } await _bookRepository.InsertAsync( new Book(_guidGenerator.Create(), "Sample Book", 19.99m, Guid.Empty), autoSave: true ); } } ```
Auf GitHub ansehen