I am using ABP Framework (ABP Suite) in a Monolithic Modular architecture (DDD model).
In one of my entities, I used a File type property to store a file as a blob. For this purpose, I configured the database blob provider inside my module.
Configuration
Inside XXXXEntityFrameworkCoreModule : AbpModule, I added the following configuration:
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.ConfigureDefault(container =>
{
container.UseDatabase();
});
});
The project compiles successfully.
Migration Generation
I prefer to store module-specific migrations within the module itself, so I generated the migration using the following command:
dotnet ef migrations add Add_PSPluginVersion \
--context ConnectDbContext \
--project "$(git rev-parse --show-toplevel)/modules/connect/src/Mantle.Connect.EntityFrameworkCore/" \
--startup-project "$(git rev-parse --show-toplevel)/src/Mantle.PowerAut0mater.HttpApi.Host/"
Issue
The migration was generated with the following table creation statements:
AbpBlobContainersAbpBlobs
However, these tables already exist in the database, so applying the migration results in an error due to duplicate table creation.
Generated migration snippet:
migrationBuilder.CreateTable(
name: "AbpBlobContainers",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(128)", maxLength: 128, nullable: false),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBlobContainers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AbpBlobs",
columns: table => new
{
Id = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
ContainerId = table.Column<Guid>(type: "uniqueidentifier", nullable: false),
TenantId = table.Column<Guid>(type: "uniqueidentifier", nullable: true),
Name = table.Column<string>(type: "nvarchar(256)", maxLength: 256, nullable: false),
Content = table.Column<byte[]>(type: "varbinary(max)", maxLength: 2147483647, nullable: true),
ExtraProperties = table.Column<string>(type: "nvarchar(max)", nullable: false),
ConcurrencyStamp = table.Column<string>(type: "nvarchar(40)", maxLength: 40, nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AbpBlobs", x => x.Id);
table.ForeignKey(
name: "FK_AbpBlobs_AbpBlobContainers_ContainerId",
column: x => x.ContainerId,
principalTable: "AbpBlobContainers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
Problem
These tables are already available in the database, likely created by the main application migration. However, when generating migrations inside the module, the system attempts to recreate them, causing migration conflicts.
Question
What is the recommended approach when using the Database Blob Provider in a modular monolithic architecture where:
- Each module maintains its own migrations
- Shared ABP infrastructure tables (like
AbpBlobsandAbpBlobContainers) already exist in the main database
How can I prevent the migration generator from recreating these existing ABP blob tables?
Project Structure
modules/
connect/
src/
Mantle.Connect.EntityFrameworkCore
Mantle.Connect.Domain
Mantle.Connect.Application
...
src/
Mantle.PowerAut0mater.EntityFrameworkCore
Mantle.PowerAut0mater.HttpApi.Host
...
3 Answer(s)
-
0
In ABP, the Database BLOB Provider tables (
AbpBlobContainers,AbpBlobs) are added to the EF Core model only if the DbContext includes the BLOB-Storing model configuration (i.e., thebuilder.ConfigureBlobStoring()mappings are part of that DbContext’sOnModelCreating).When you run
dotnet ef migrations add ... --context ConnectDbContext, EF compares:- the current model of
ConnectDbContextand - the last model snapshot for
ConnectDbContext
If your
ConnectDbContextcurrently includesConfigureBlobStoring()but the snapshot (or previous module migrations history) didn’t, EF thinks these tables are new for that context and generatesCreateTablefor them—even if they already exist in the physical database due to the main app’s migration history.- the current model of
Recommended approach (modular monolith + per-module migrations)
Pick a single “owner” migration DbContext for shared ABP infrastructure tables, and generate/apply those tables only from that owner.
- For BLOB database provider tables, that means: only one migrations DbContext in the solution should include
builder.ConfigureBlobStoring(). - Typically, this is your main application MigrationsDbContext (the one that already created them in the “main application migration”).
- For BLOB database provider tables, that means: only one migrations DbContext in the solution should include
Do NOT include Blob-Storing model mappings in module-specific DbContexts that maintain their own migrations, unless that module is intended to “own” those tables in its own migrations history.
- In practice: remove/avoid calling
builder.ConfigureBlobStoring()inConnectDbContext(or in that module’s migrations DbContext). - You can still use blob storing (runtime configuration like
container.UseDatabase()is fine), but schema creation forAbpBlobs/AbpBlobContainersshould come from the single owner migrations set.
- In practice: remove/avoid calling
If you already generated a module migration that contains these
CreateTablecalls:- Delete that migration (and snapshot changes) and regenerate after ensuring the module DbContext doesn’t include the blob-storing mappings, or
- Keep the migration but manually remove the
CreateTableforAbpBlobContainers/AbpBlobs(and corresponding indexes/FKs) so the module migration only contains module-owned schema changes.
This keeps each module’s migrations independent while preventing “shared infrastructure” tables from being created multiple times by different migration histories.
Sources:
- https://abp.io/docs/10.1/framework/infrastructure/blob-storing/database
- https://abp.io/docs/10.1/modules/database-tables
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
-
0
I have removed
builder.ConfigureBlobStoring()from the modulepublic class ConnectDbContext : AbpDbContext<ConnectDbContext>, IConnectDbContextand every thing worked as expected -
0
Great