- **Do** define an **interface** for the `DbContext` that inherits from `IEfCoreDbContext`.
- **Do** define an **interface** for the `DbContext` that inherits from `IEfCoreDbContext`.
- **Do** add a `ConnectionStringName`**attribute** to the `DbContext` interface.
- **Do** add a `ConnectionStringName`**attribute** to the `DbContext` interface.
- **Do** add `DbSet<T>`**properties** to the `DbContext` interface for only aggregate roots. Example:
- **Do** add `DbSet<TEntity>`**properties** to the `DbContext` interface for only aggregate roots. Example:
````C#
````C#
[ConnectionStringName("AbpIdentity")]
[ConnectionStringName("AbpIdentity")]
public interface IIdentityDbContext : IEfCoreDbContext
public interface IIdentityDbContext : IEfCoreDbContext
{
{
DbSet<IdentityUser> Users { get; set; }
DbSet<IdentityUser> Users { get; set; }
DbSet<IdentityRole> Roles { get; set; }
DbSet<IdentityRole> Roles { get; set; }
}
}
````
````
@ -125,14 +124,13 @@ public interface IIdentityDbContext : IEfCoreDbContext
* **Do** inherit the `DbContext` from the `AbpDbContext<TDbContext>` class.
* **Do** inherit the `DbContext` from the `AbpDbContext<TDbContext>` class.
* **Do** add a `ConnectionStringName` attribute to the `DbContext` class.
* **Do** add a `ConnectionStringName` attribute to the `DbContext` class.
* **Do** implement the repository`interface` for the `DbContext` class. Example:
* **Do** implement the corresponding`interface` for the `DbContext` class. Example:
````C#
````C#
[ConnectionStringName("AbpIdentity")]
[ConnectionStringName("AbpIdentity")]
public class IdentityDbContext : AbpDbContext<IdentityDbContext>, IIdentityDbContext
public class IdentityDbContext : AbpDbContext<IdentityDbContext>, IIdentityDbContext
{
{
public DbSet<IdentityUser> Users { get; set; }
public DbSet<IdentityUser> Users { get; set; }
public DbSet<IdentityRole> Roles { get; set; }
public DbSet<IdentityRole> Roles { get; set; }
public IdentityDbContext(DbContextOptions<IdentityDbContext> options)
public IdentityDbContext(DbContextOptions<IdentityDbContext> options)
@ -147,15 +145,14 @@ public class IdentityDbContext : AbpDbContext<IdentityDbContext>, IIdentityDbCon
###### Table Prefix and Schema
###### Table Prefix and Schema
- **Do** add static `TablePrefix` and `Schema` properties to the `DbContext` class. Set default value from an constant. Example:
- **Do** add static `TablePrefix` and `Schema`**properties** to the `DbContext` class. Set default value from a constant. Example:
````C#
````C#
public static string TablePrefix { get; set; } = AbpIdentityConsts.DefaultDbTablePrefix;
public static string TablePrefix { get; set; } = AbpIdentityConsts.DefaultDbTablePrefix;
public static string Schema { get; set; } = AbpIdentityConsts.DefaultDbSchema;
public static string Schema { get; set; } = AbpIdentityConsts.DefaultDbSchema;
````
````
- **Do** always use a short `TablePrefix` value for a module to create unique table names in a shared database. `Abp` table prefix is reserved for ABP core modules.
- **Do** always use a short `TablePrefix` value for a module to create **unique table names** in a shared database. `Abp` table prefix is reserved for ABP core modules.
- **Do** set `Schema` to `null` as default.
- **Do** set `Schema` to `null` as default.
###### Model Mapping
###### Model Mapping
@ -214,7 +211,6 @@ public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfiguratio
- **Do** add implemented repositories to the options for the `AddAbpDbContext<TDbContext>` method. Example:
- **Do** add implemented repositories to the options for the `AddAbpDbContext<TDbContext>` method. Example:
````C#
````C#
[DependsOn(typeof(AbpIdentityDomainModule))]
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpEntityFrameworkCoreModule)
)]
public class AbpIdentityEntityFrameworkCoreModule : AbpModule
public class AbpIdentityEntityFrameworkCoreModule : AbpModule
{
{
public override void ConfigureServices(IServiceCollection services)
public override void ConfigureServices(IServiceCollection services)
@ -308,4 +308,206 @@ public class AbpIdentityEntityFrameworkCoreModule : AbpModule
}
}
````
````
##### MongoDB
##### MongoDB
* Do define a separated `DbContext` interface and class for each module.
###### MongoDbContext Interface
- **Do** define an **interface** for the `MongoDbContext` that inherits from `IAbpMongoDbContext`.
- **Do** add a `ConnectionStringName`**attribute** to the `MongoDbContext` interface.
- **Do** add `IMongoCollection<TEntity>`**properties** to the `MongoDbContext` interface for only aggregate roots. Example:
````C#
[ConnectionStringName("AbpIdentity")]
public interface IAbpIdentityMongoDbContext : IAbpMongoDbContext
{
IMongoCollection<IdentityUser> Users { get; }
IMongoCollection<IdentityRole> Roles { get; }
}
````
###### MongoDbContext class
- **Do** inherit the `MongoDbContext` from the `AbpMongoDbContext` class.
- **Do** add a `ConnectionStringName` attribute to the `MongoDbContext` class.
- **Do** implement the corresponding `interface` for the `MongoDbContext` class. Example:
```c#
[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 `CollectionPrefix`**property** to the `DbContext` class. Set default value from a constant. Example:
```c#
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 `CollectionPrefix` value for a module to create **unique collection names** in a shared database. `Abp` collection prefix is reserved for ABP core modules.
###### Collection Mapping
- **Do** explicitly **configure all entities** by overriding the `CreateModel` method of the `MongoDbContext`. Example:
- **Do not** configure model directly in the `CreateModel` method. Instead, create an **extension method** for `IMongoModelBuilder`. Use Configure*ModuleName* as the method name. Example:
```c#
public static class AbpIdentityMongoDbContextExtensions
`BsonClassMap` works with static methods. So, it is only needed to configure entities once in an application. `OneTimeRunner` guarantees it in a thread safe manner. 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:
- **Do** pass the `cancellationToken` to the MongoDB Driver using the `GetCancellationToken` helper method. Example:
```c#
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 `includeDetails` parameters 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 an `IQueryable<TEntity>` to perform queries wherever possible. Because;
* `GetMongoQueryable()` method automatically uses the `ApplyDataFilters` method 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 the `GetMongoQueryable()` method is not possible to use.
###### Module Class
- **Do** define a module class for the MongoDB integration package.
- **Do** add `MongoDbContext` to the `IServiceCollection` using the `AddMongoDbContext<TMongoDbContext>` method.
- **Do** add implemented repositories to the options for the `AddMongoDbContext<TMongoDbContext>` method. Example:
```c#
[DependsOn(
typeof(AbpIdentityDomainModule),
typeof(AbpUsersMongoDbModule)
)]
public class AbpIdentityMongoDbModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)