mirror of https://github.com/abpframework/abp
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.1 KiB
6.1 KiB
MongoDB Integration
- Do define a separated
MongoDbContextinterface and class for each module.
MongoDbContext Interface
- Do define an interface for the
MongoDbContextthat inherits fromIAbpMongoDbContext. - Do add a
ConnectionStringNameattribute to theMongoDbContextinterface. - Do add
IMongoCollection<TEntity>properties to theMongoDbContextinterface only for the aggregate roots. Example:
[ConnectionStringName("AbpIdentity")]
public interface IAbpIdentityMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<IdentityUser> Users { get; }
IMongoCollection<IdentityRole> Roles { get; }
}
MongoDbContext class
- Do inherit the
MongoDbContextfrom theAbpMongoDbContextclass. - Do add a
ConnectionStringNameattribute to theMongoDbContextclass. - Do implement the corresponding
interfacefor theMongoDbContextclass. Example:
[ConnectionStringName("AbpIdentity")]
public class AbpIdentityMongoDbContext : AbpMongoDbContext, IAbpIdentityMongoDbContext
{
public IMongoCollection<IdentityUser> Users => Collection<IdentityUser>();
public IMongoCollection<IdentityRole> Roles => Collection<IdentityRole>();
//code omitted for brevity
}
Collection Prefix
- Do add static
CollectionPrefixproperty to theDbContextclass. Set default value from a constant. Example:
public static string CollectionPrefix { get; set; } = AbpIdentityConsts.DefaultDbTablePrefix;
Used the same constant defined for the EF Core integration table prefix in this example.
- Do always use a short
CollectionPrefixvalue for a module to create unique collection names in a shared database.Abpcollection prefix is reserved for ABP core modules.
Collection Mapping
- Do explicitly configure all aggregate roots by overriding the
CreateModelmethod of theMongoDbContext. Example:
protected override void CreateModel(IMongoModelBuilder modelBuilder)
{
base.CreateModel(modelBuilder);
modelBuilder.ConfigureIdentity(options =>
{
options.CollectionPrefix = CollectionPrefix;
});
}
- Do not configure model directly in the
CreateModelmethod. Instead, create an extension method for theIMongoModelBuilder. Use ConfigureModuleName as the method name. Example:
public static class AbpIdentityMongoDbContextExtensions
{
public static void ConfigureIdentity(
this IMongoModelBuilder builder,
Action<IdentityMongoModelBuilderConfigurationOptions> optionsAction = null)
{
Check.NotNull(builder, nameof(builder));
var options = new IdentityMongoModelBuilderConfigurationOptions();
optionsAction?.Invoke(options);
builder.Entity<IdentityUser>(b =>
{
b.CollectionName = options.CollectionPrefix + "Users";
});
builder.Entity<IdentityRole>(b =>
{
b.CollectionName = options.CollectionPrefix + "Roles";
});
}
}
- Do create a configuration options class by inheriting from the
AbpMongoModelBuilderConfigurationOptions. Example:
public class IdentityMongoModelBuilderConfigurationOptions
: AbpMongoModelBuilderConfigurationOptions
{
public IdentityMongoModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix)
{
}
}
Repository Implementation
- Do inherit the repository from the
MongoDbRepository<TMongoDbContext, TEntity, TKey>class and implement the corresponding repository interface. Example:
public class MongoIdentityUserRepository
: MongoDbRepository<IAbpIdentityMongoDbContext, IdentityUser, Guid>,
IIdentityUserRepository
{
public MongoIdentityUserRepository(
IMongoDbContextProvider<IAbpIdentityMongoDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
- Do pass the
cancellationTokento the MongoDB Driver using theGetCancellationTokenhelper method. Example:
public async Task<IdentityUser> FindByNormalizedUserNameAsync(
string normalizedUserName,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await GetMongoQueryable()
.FirstOrDefaultAsync(
u => u.NormalizedUserName == normalizedUserName,
GetCancellationToken(cancellationToken)
);
}
GetCancellationToken fallbacks to the ICancellationTokenProvider.Token to obtain the cancellation token if it is not provided by the caller code.
- Do ignore the
includeDetailsparameters for the repository implementation since MongoDB loads the aggregate root as a whole (including sub collections) by default. - Do use the
GetMongoQueryable()method to obtain anIQueryable<TEntity>to perform queries wherever possible. Because;GetMongoQueryable()method automatically uses theApplyDataFiltersmethod to filter the data based on the current data filters (like soft delete and multi-tenancy).- Using
IQueryable<TEntity>makes the code as much as similar to the EF Core repository implementation and easy to write and read.
- Do implement data filtering if it is not possible to use the
GetMongoQueryable()method.
Module Class
- Do define a module class for the MongoDB integration package.
- Do add
MongoDbContextto theIServiceCollectionusing theAddMongoDbContext<TMongoDbContext>method. - Do add implemented repositories to the options for the
AddMongoDbContext<TMongoDbContext>method. Example:
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpUsersMongoDbModule)
)]
public class AbpIdentityMongoDbModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMongoDbContext<AbpIdentityMongoDbContext>(options =>
{
options.AddRepository<IdentityUser, MongoIdentityUserRepository>();
options.AddRepository<IdentityRole, MongoIdentityRoleRepository>();
});
}
}
Notice that this module class also calls the static BsonClassMap configuration method defined above.