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.
7.1 KiB
7.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
MongoModelBuilderConfigurationOptions. Example:
public class IdentityMongoModelBuilderConfigurationOptions
: MongoModelBuilderConfigurationOptions
{
public IdentityMongoModelBuilderConfigurationOptions()
: base(AbpIdentityConsts.DefaultDbTablePrefix)
{
}
}
- Do explicitly configure
BsonClassMapfor all entities. Create a static method for this purpose. Example:
public static class AbpIdentityBsonClassMap
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
BsonClassMap.RegisterClassMap<IdentityUser>(map =>
{
map.AutoMap();
map.ConfigureExtraProperties();
});
BsonClassMap.RegisterClassMap<IdentityRole>(map =>
{
map.AutoMap();
});
});
}
}
BsonClassMap works with static methods. So, it is only needed to configure entities once in an application. OneTimeRunner guarantees that it runs in a thread safe manner and only once in the application life. Such a mapping above ensures that unit test properly run. This code will be called by the module class below.
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)
{
AbpIdentityBsonClassMap.Configure();
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.