Revised repository registration system.

pull/272/head
Halil İbrahim Kalkan 8 years ago
parent cf8c963422
commit 76d461df0e

@ -160,7 +160,7 @@ public static string Schema { get; set; } = AbpIdentityConsts.DefaultDbSchema;
###### Model Mapping
- **Do** explicitly configure all entities by overriding the `OnModelCreating` method of the `DbContext`. Example:
- **Do** explicitly **configure all entities** by overriding the `OnModelCreating` method of the `DbContext`. Example:
````C#
protected override void OnModelCreating(ModelBuilder builder)
@ -175,7 +175,7 @@ protected override void OnModelCreating(ModelBuilder builder)
}
````
- **Do not** configure model directly in the `OnModelCreating` method. Instead, create an extension method for `ModelBuilder`. Use Configure*ModuleName* as the method name. Example:
- **Do not** configure model directly in the `OnModelCreating` method. Instead, create an **extension method** for `ModelBuilder`. Use Configure*ModuleName* as the method name. Example:
````C#
public static class IdentityDbContextModelBuilderExtensions
@ -206,7 +206,7 @@ public static class IdentityDbContextModelBuilderExtensions
}
````
* Do create a configuration options class by inheriting from the `ModelBuilderConfigurationOptions`. Example:
* **Do** create a **configuration options** class by inheriting from the `ModelBuilderConfigurationOptions`. Example:
````C#
public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfigurationOptions
@ -219,12 +219,93 @@ public class IdentityModelBuilderConfigurationOptions : ModelBuilderConfiguratio
}
````
###### Repository Implementation
- **Do** **inherit** the repository from the `EfCoreRepository<TDbContext, TEntity, TKey>` class and implement the corresponding repository interface. Example:
````C#
public class EfCoreIdentityUserRepository
: EfCoreRepository<IIdentityDbContext, IdentityUser, Guid>, IIdentityUserRepository
{
public EfCoreIdentityUserRepository(
IDbContextProvider<IIdentityDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
}
````
* **Do** pass the `cancellationToken` to EF Core using the `GetCancellationToken` helper method. Example:
````C#
public virtual async Task<IdentityUser> FindByNormalizedUserNameAsync(
string normalizedUserName,
bool includeDetails = true,
CancellationToken cancellationToken = default)
{
return await DbSet
.IncludeDetails(includeDetails)
.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** create a `IncludeDetails` **extension method** for the `IQueryable<TEntity>` for each aggregate root which has **sub collections**. Example:
````C#
public static IQueryable<IdentityUser> IncludeDetails(
this IQueryable<IdentityUser> queryable,
bool include = true)
{
if (!include)
{
return queryable;
}
return queryable
.Include(x => x.Roles)
.Include(x => x.Logins)
.Include(x => x.Claims)
.Include(x => x.Tokens);
}
````
* **Do** use the `IncludeDetails` extension method in the repository methods just like used in the example code above (see FindByNormalizedUserNameAsync).
- **Do** override `IncludeDetails` method of the repository for aggregates root which have **sub collections**. Example:
````C#
protected override IQueryable<IdentityUser> IncludeDetails(IQueryable<IdentityUser> queryable)
{
return queryable.IncludeDetails(); //uses the extension method defined above
}
````
###### Module Class
Define
- **Do** define a module class for the Entity Framework Core integration package.
- **Do** add `DbContext` to the `IServiceCollection` using the `AddAbpDbContext<TDbContext>` method.
- **Do** add implemented repositories to the options for the `AddAbpDbContext<TDbContext>` method. Example:
###### Repository Implementation
````C#
[DependsOn(typeof(AbpIdentityDomainModule))]
public class AbpIdentityEntityFrameworkCoreModule : AbpModule
{
public override void ConfigureServices(IServiceCollection services)
{
services.AddAbpDbContext<IdentityDbContext>(options =>
{
options.AddRepository<IdentityUser, EfCoreIdentityUserRepository>();
options.AddRepository<IdentityRole, EfCoreIdentityRoleRepository>();
});
-
services.AddAssemblyOf<AbpIdentityEntityFrameworkCoreModule>();
}
}
````
##### MongoDB

@ -31,7 +31,7 @@ namespace Volo.Abp.Domain.Repositories
protected virtual void RegisterDefaultRepositories(IServiceCollection services)
{
foreach (var entityType in GetEntityTypes(Options.DefaultRepositoryDbContextType))
foreach (var entityType in GetEntityTypes(Options.OriginalDbContextType))
{
if (!ShouldRegisterDefaultRepositoryFor(entityType))
{

@ -17,14 +17,8 @@ namespace Microsoft.Extensions.DependencyInjection
var options = new AbpDbContextRegistrationOptions(typeof(TDbContext));
optionsBuilder?.Invoke(options);
services.TryAddTransient<TDbContext>();
services.TryAddTransient(DbContextOptionsFactory.Create<TDbContext>);
if (options.DefaultRepositoryDbContextType != typeof(TDbContext))
{
services.TryAddTransient(options.DefaultRepositoryDbContextType, typeof(TDbContext));
}
foreach (var dbContextType in options.ReplacedDbContextTypes)
{
services.Replace(ServiceDescriptor.Transient(dbContextType, typeof(TDbContext)));

@ -11,6 +11,7 @@ using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Metadata;
using Volo.Abp.Auditing;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Entities;
using Volo.Abp.Domain.Entities.Events;
using Volo.Abp.Guids;
@ -19,7 +20,7 @@ using Volo.Abp.Reflection;
namespace Volo.Abp.EntityFrameworkCore
{
public abstract class AbpDbContext<TDbContext> : DbContext, IEfCoreDbContext
public abstract class AbpDbContext<TDbContext> : DbContext, IEfCoreDbContext, ITransientDependency
where TDbContext : DbContext
{
protected virtual Guid? CurrentTenantId => CurrentTenant?.Id;

@ -13,8 +13,6 @@ namespace Microsoft.Extensions.DependencyInjection
var options = new MemoryDbContextRegistrationOptions(typeof(TMemoryDbContext));
optionsBuilder?.Invoke(options);
services.AddSingleton<TMemoryDbContext>();
if (options.DefaultRepositoryDbContextType != typeof(TMemoryDbContext))
{
services.TryAddSingleton(options.DefaultRepositoryDbContextType, sp => sp.GetRequiredService<TMemoryDbContext>());

@ -1,9 +1,10 @@
using System;
using System.Collections.Generic;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MemoryDb
{
public abstract class MemoryDbContext
public abstract class MemoryDbContext : ISingletonDependency
{
private static readonly Type[] EmptyTypeList = new Type[0];

@ -13,16 +13,9 @@ namespace Microsoft.Extensions.DependencyInjection
var options = new MongoDbContextRegistrationOptions(typeof(TMongoDbContext));
optionsBuilder?.Invoke(options);
services.TryAddSingleton<TMongoDbContext>();
if (options.DefaultRepositoryDbContextType != typeof(TMongoDbContext))
{
services.TryAddSingleton(options.DefaultRepositoryDbContextType, sp => sp.GetRequiredService<TMongoDbContext>());
}
foreach (var dbContextType in options.ReplacedDbContextTypes)
{
services.Replace(ServiceDescriptor.Singleton(dbContextType, sp => sp.GetRequiredService<TMongoDbContext>()));
services.Replace(ServiceDescriptor.Transient(dbContextType, typeof(TMongoDbContext)));
}
new MongoDbRepositoryRegistrar(options)

@ -1,9 +1,10 @@
using System.Collections.Generic;
using MongoDB.Driver;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.MongoDB
{
public abstract class AbpMongoDbContext : IAbpMongoDbContext
public abstract class AbpMongoDbContext : IAbpMongoDbContext, ITransientDependency
{
public IMongoModelSource ModelSource { get; set; }

@ -51,8 +51,7 @@ namespace Volo.Abp.Uow.MongoDB
var dbContext = unitOfWork.ServiceProvider.GetRequiredService<TMongoDbContext>();
var abpDbContext = unitOfWork.ServiceProvider.GetRequiredService<TMongoDbContext>().ToAbpMongoDbContext();
abpDbContext.InitializeDatabase(database);
dbContext.ToAbpMongoDbContext().InitializeDatabase(database);
return new MongoDbDatabaseApi<TMongoDbContext>(dbContext);
});

Loading…
Cancel
Save