Class IdentityDbContextBase<TUser, TRole, TIdentityKey>
- Namespace
- NuvTools.Security.Identity.EntityFrameworkCore
- Assembly
- NuvTools.Security.Identity.EntityFrameworkCore.dll
Provides a base implementation of IdentityDbContext<TUser, TRole, TKey> with enhanced transaction support, execution strategies, and batch operation capabilities.
public abstract class IdentityDbContextBase<TUser, TRole, TIdentityKey> : IdentityDbContext<TUser, TRole, TIdentityKey>, IInfrastructure<IServiceProvider>, IDbContextDependencies, IDbSetCache, IDbContextPoolable, IResettableService, IDisposable, IAsyncDisposable, IDbContextCommands, IDbContextWithListCommands where TUser : IdentityUser<TIdentityKey> where TRole : IdentityRole<TIdentityKey> where TIdentityKey : IEquatable<TIdentityKey>
Type Parameters
TUserThe type representing a user in the system, must inherit from IdentityUser<TKey>.
TRoleThe type representing a role in the system, must inherit from IdentityRole<TKey>.
TIdentityKeyThe type of the primary key for users and roles, must implement IEquatable<T>.
- Inheritance
-
IdentityUserContext<TUser, TIdentityKey, IdentityUserClaim<TIdentityKey>, IdentityUserLogin<TIdentityKey>, IdentityUserToken<TIdentityKey>, IdentityUserPasskey<TIdentityKey>>IdentityDbContext<TUser, TRole, TIdentityKey, IdentityUserClaim<TIdentityKey>, IdentityUserRole<TIdentityKey>, IdentityUserLogin<TIdentityKey>, IdentityRoleClaim<TIdentityKey>, IdentityUserToken<TIdentityKey>, IdentityUserPasskey<TIdentityKey>>IdentityDbContext<TUser, TRole, TIdentityKey, IdentityUserClaim<TIdentityKey>, IdentityUserRole<TIdentityKey>, IdentityUserLogin<TIdentityKey>, IdentityRoleClaim<TIdentityKey>, IdentityUserToken<TIdentityKey>>IdentityDbContext<TUser, TRole, TIdentityKey>IdentityDbContextBase<TUser, TRole, TIdentityKey>
- Implements
- Inherited Members
Examples
public class ApplicationDbContext : IdentityDbContextBase<ApplicationUser, ApplicationRole, Guid>
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Configure your entities here
}
}
Remarks
This abstract base class extends IdentityDbContext<TUser, TRole, TKey> and implements IDbContextCommands and IDbContextWithListCommands to provide:
- Transaction management with begin, commit, and rollback operations
- Execution strategies for handling transient database failures
- Convenient CRUD operations that automatically save changes and return IResult wrappers
- Batch operations for synchronizing collections of entities
- Support for composite key operations
All operations use the Result pattern, returning IResult or IResult<T> instead of throwing exceptions for business logic failures.
Constructors
IdentityDbContextBase()
Initializes a new instance of the IdentityDbContextBase<TUser, TRole, TIdentityKey> class.
protected IdentityDbContextBase()
Remarks
This parameterless constructor is typically used for design-time tools and migrations.
IdentityDbContextBase(DbContextOptions)
Initializes a new instance of the IdentityDbContextBase<TUser, TRole, TIdentityKey> class with the specified options.
protected IdentityDbContextBase(DbContextOptions options)
Parameters
optionsDbContextOptionsThe options to be used by the DbContext.
Remarks
This constructor is used for runtime configuration and dependency injection scenarios.
Properties
CurrentTransaction
Gets the current active transaction, or null if no transaction is active.
public IDbContextTransaction? CurrentTransaction { get; }
Property Value
- IDbContextTransaction
An IDbContextTransaction representing the current transaction, or null if no transaction has been started.
Remarks
Use this property to check whether a transaction is currently active before performing transaction-specific operations.
Methods
AcquireTransactionLockAsync(string, CancellationToken)
Acquires an exclusive, database-wide lock identified by name, held until the current
transaction commits or rolls back.
public Task AcquireTransactionLockAsync(string name, CancellationToken cancellationToken = default)
Parameters
namestringLock name. Identifies what is being serialized, e.g.
"contract-number:53".cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task
A task that completes once the lock is held.
Remarks
The provider-specific statement is resolved from IDbContextTransactionLock, registered by the
provider package's AddDatabase helpers. When none is registered (e.g. an in-memory context built by
hand in a test) the call is a no-op.
Exceptions
- ArgumentException
Thrown when
nameis null, empty or whitespace.- InvalidOperationException
Thrown when there is no active transaction.
AddAndSaveAsync<TEntity, TKey>(TEntity, CancellationToken)
Asynchronously adds an entity to the database and saves the changes, returning the generated primary key.
public Task<IResult<TKey>> AddAndSaveAsync<TEntity, TKey>(TEntity entity, CancellationToken cancellationToken = default) where TEntity : class
Parameters
entityTEntityThe entity instance to add to the database.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult<TKey>>
A task that represents the asynchronous operation. The task result contains an IResult<T> with the generated primary key value if successful.
Type Parameters
TEntityThe type of entity to add. Must be a reference type.
TKeyThe type of the primary key.
Remarks
This method automatically calls SaveChangesAsync(CancellationToken) after adding the entity. The result will contain the primary key value generated by the database (for identity columns or sequences).
AddAndSaveWithCompositeKeyAsync<TEntity>(TEntity, CancellationToken)
Asynchronously adds an entity with a composite key to the database and saves the changes, returning the composite key values.
public Task<IResult<object[]>> AddAndSaveWithCompositeKeyAsync<TEntity>(TEntity entity, CancellationToken cancellationToken = default) where TEntity : class
Parameters
entityTEntityThe entity instance to add to the database.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult<object[]>>
A task that represents the asynchronous operation. The task result contains an IResult<T> with an array of composite key values if successful.
Type Parameters
TEntityThe type of entity to add. Must be a reference type.
Remarks
This method is used for entities that have composite primary keys (multiple columns forming the primary key). The returned array contains the key values in the order they are defined in the entity configuration.
AddOrRemoveFromListAsync<TEntity, TKey>(IEnumerable<TEntity>, Func<TEntity, TKey>, Expression<Func<TEntity, bool>>?, CancellationToken)
Asynchronously adds new entities from a collection or removes existing ones that are not in the collection, without updating existing entities.
public Task<IResult> AddOrRemoveFromListAsync<TEntity, TKey>(IEnumerable<TEntity> entities, Func<TEntity, TKey> keySelector, Expression<Func<TEntity, bool>>? filter = null, CancellationToken cancellationToken = default) where TEntity : class where TKey : notnull
Parameters
entitiesIEnumerable<TEntity>The collection of entities to ensure exist in the database.
keySelectorFunc<TEntity, TKey>A function to extract the key from an entity for comparison.
filterExpression<Func<TEntity, bool>>An optional filter expression to limit which database entities are considered for removal.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the operation was successful.
Type Parameters
TEntityThe type of entity to add or remove. Must be a reference type.
TKeyThe type of the key used to identify entities. Must be non-nullable.
Examples
// Ensure specific tags exist for a post without updating existing tag data
var tags = new[] { "C#", "ASP.NET", "EF Core" }.Select(t => new Tag { Name = t, PostId = postId });
await context.AddOrRemoveFromListAsync(tags, t => t.Name, t => t.PostId == postId);
Remarks
This method performs selective add/remove operations:
- Entities in the collection but not in the database are added
- Entities in the database (matching the filter) but not in the collection are removed
- Existing entities that are in both the collection and database are left unchanged (not updated)
This is useful when you only care about the presence of entities, not their current values.
AddOrUpdateFromListAsync<TEntity, TKey>(IEnumerable<TEntity>, Func<TEntity, TKey>, Expression<Func<TEntity, bool>>?, CancellationToken)
Asynchronously adds new entities from a collection or updates existing ones, without removing any entities.
public Task<IResult> AddOrUpdateFromListAsync<TEntity, TKey>(IEnumerable<TEntity> entities, Func<TEntity, TKey> keySelector, Expression<Func<TEntity, bool>>? filter = null, CancellationToken cancellationToken = default) where TEntity : class where TKey : notnull
Parameters
entitiesIEnumerable<TEntity>The collection of entities to add or update in the database.
keySelectorFunc<TEntity, TKey>A function to extract the key from an entity for comparison.
filterExpression<Func<TEntity, bool>>An optional filter expression to limit which database entities are considered for matching.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the operation was successful.
Type Parameters
TEntityThe type of entity to add or update. Must be a reference type.
TKeyThe type of the key used to identify entities. Must be non-nullable.
Examples
// Add or update permissions without removing existing ones
var permissions = new[] { "Read", "Write", "Execute" }.Select(p => new Permission { Name = p });
await context.AddOrUpdateFromListAsync(permissions, p => p.Name);
Remarks
This method performs an upsert operation:
- Entities not found in the database are added
- Entities found in the database are updated with values from the collection
- No entities are removed from the database
This is useful when you want to ensure certain entities exist and are up-to-date without deleting others.
BeginTransactionAsync(CancellationToken)
Asynchronously begins a new database transaction.
public Task<IDbContextTransaction> BeginTransactionAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IDbContextTransaction>
A task that represents the asynchronous operation. The task result contains an IDbContextTransaction that represents the started transaction.
Remarks
Transactions allow multiple database operations to be executed as a single atomic unit. Use CommitTransactionAsync(CancellationToken) to commit the transaction or RollbackTransactionAsync(CancellationToken) to roll it back.
CommitTransactionAsync(CancellationToken)
Asynchronously commits all changes made in the current transaction to the database.
public Task CommitTransactionAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task
A task that represents the asynchronous operation.
Remarks
This method should be called after BeginTransactionAsync(CancellationToken) to persist the changes. If the commit fails, the transaction remains active and can be rolled back.
Exceptions
- InvalidOperationException
Thrown when there is no active transaction.
ExecuteWithStrategyAsync(Func<CancellationToken, Task>, CancellationToken)
Executes an action within the configured execution strategy to handle transient database failures.
public Task ExecuteWithStrategyAsync(Func<CancellationToken, Task> action, CancellationToken cancellationToken = default)
Parameters
actionFunc<CancellationToken, Task>The action to execute that takes a CancellationToken and returns a Task.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task
A task that represents the asynchronous operation.
Remarks
The execution strategy automatically retries operations that fail due to transient errors, such as temporary network issues or database deadlocks, according to the configured retry policy.
ExecuteWithStrategyAsync<T>(Func<CancellationToken, Task<T>>, CancellationToken)
Executes a function within the configured execution strategy to handle transient database failures.
public Task<T> ExecuteWithStrategyAsync<T>(Func<CancellationToken, Task<T>> action, CancellationToken cancellationToken = default)
Parameters
actionFunc<CancellationToken, Task<T>>The function to execute that takes a CancellationToken and returns a Task<TResult>.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<T>
A task that represents the asynchronous operation. The task result contains the value returned by the function.
Type Parameters
TThe type of the result returned by the function.
Remarks
The execution strategy automatically retries operations that fail due to transient errors, such as temporary network issues or database deadlocks, according to the configured retry policy.
RemoveAndSaveAsync<TEntity>(params object[])
Asynchronously removes an entity from the database by its primary key and saves the changes.
public Task<IResult> RemoveAndSaveAsync<TEntity>(params object[] keyValues) where TEntity : class
Parameters
keyValuesobject[]The primary key values identifying the entity to remove.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the removal was successful.
Type Parameters
TEntityThe type of entity to remove. Must be a reference type.
Remarks
This method finds the entity by its primary key, removes it, and automatically saves the changes. If the entity is not found, the operation may still succeed (idempotent deletion).
RemoveAndSaveAsync<TEntity>(object[], CancellationToken)
Asynchronously removes an entity from the database by its primary key and saves the changes.
public Task<IResult> RemoveAndSaveAsync<TEntity>(object[] keyValues, CancellationToken cancellationToken = default) where TEntity : class
Parameters
keyValuesobject[]The primary key values identifying the entity to remove.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the removal was successful.
Type Parameters
TEntityThe type of entity to remove. Must be a reference type.
Remarks
This method finds the entity by its primary key, removes it, and automatically saves the changes. If the entity is not found, the operation may still succeed (idempotent deletion).
RollbackTransactionAsync(CancellationToken)
Asynchronously rolls back all changes made in the current transaction.
public Task RollbackTransactionAsync(CancellationToken cancellationToken = default)
Parameters
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task
A task that represents the asynchronous operation.
Remarks
This method discards all changes made within the current transaction and closes it. After rolling back, you need to call BeginTransactionAsync(CancellationToken) to start a new transaction.
Exceptions
- InvalidOperationException
Thrown when there is no active transaction.
SyncFromListAsync<TEntity, TKey>(IEnumerable<TEntity>, Func<TEntity, TKey>, Expression<Func<TEntity, bool>>?, CancellationToken)
Asynchronously synchronizes a collection of entities with the database by adding new entities, updating existing ones, and removing entities not present in the collection.
public Task<IResult> SyncFromListAsync<TEntity, TKey>(IEnumerable<TEntity> entities, Func<TEntity, TKey> keySelector, Expression<Func<TEntity, bool>>? filter = null, CancellationToken cancellationToken = default) where TEntity : class where TKey : notnull
Parameters
entitiesIEnumerable<TEntity>The collection of entities to synchronize with the database.
keySelectorFunc<TEntity, TKey>A function to extract the key from an entity for comparison.
filterExpression<Func<TEntity, bool>>An optional filter expression to limit which database entities are considered for synchronization.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the synchronization was successful.
Type Parameters
TEntityThe type of entity to synchronize. Must be a reference type.
TKeyThe type of the key used to identify entities. Must be non-nullable.
Examples
// Synchronize user roles - adds new, updates existing, removes missing
var userRoles = newRoleIds.Select(roleId => new IdentityUserRole<Guid> { UserId = userId, RoleId = roleId });
await context.SyncFromListAsync(userRoles, ur => ur.RoleId, ur => ur.UserId == userId);
Remarks
This method performs a full synchronization:
- Entities in the collection but not in the database are added
- Entities in both the collection and database are updated with values from the collection
- Entities in the database (matching the filter) but not in the collection are removed
This is useful for maintaining master-detail relationships or synchronizing complete lists.
UpdateAndSaveAsync<TEntity>(TEntity, params object[])
Asynchronously updates an existing entity in the database and saves the changes.
public Task<IResult> UpdateAndSaveAsync<TEntity>(TEntity entity, params object[] keyValues) where TEntity : class
Parameters
entityTEntityThe entity instance with updated values.
keyValuesobject[]The primary key values used to locate the existing entity in the database.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the update was successful.
Type Parameters
TEntityThe type of entity to update. Must be a reference type.
Remarks
This method finds the entity by its primary key, updates its values, and automatically saves the changes. If the entity is not found, the operation will fail and return an unsuccessful result.
UpdateAndSaveAsync<TEntity>(TEntity, object[], CancellationToken)
Asynchronously updates an existing entity in the database and saves the changes.
public Task<IResult> UpdateAndSaveAsync<TEntity>(TEntity entity, object[] keyValues, CancellationToken cancellationToken = default) where TEntity : class
Parameters
entityTEntityThe entity instance with updated values.
keyValuesobject[]The primary key values used to locate the existing entity in the database.
cancellationTokenCancellationTokenA CancellationToken to observe while waiting for the task to complete.
Returns
- Task<IResult>
A task that represents the asynchronous operation. The task result contains an IResult indicating whether the update was successful.
Type Parameters
TEntityThe type of entity to update. Must be a reference type.
Remarks
This method finds the entity by its primary key, updates its values, and automatically saves the changes. If the entity is not found, the operation will fail and return an unsuccessful result.