mirror of https://github.com/abpframework/abp.git
43 changed files with 724 additions and 171 deletions
@ -0,0 +1,43 @@ |
|||||
|
using System; |
||||
|
using AbpDesk.Blogging; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Uow; |
||||
|
using Volo.DependencyInjection; |
||||
|
|
||||
|
namespace AbpDesk.ConsoleDemo |
||||
|
{ |
||||
|
public class BlogPostLister : ITransientDependency |
||||
|
{ |
||||
|
private readonly IQueryableRepository<BlogPost, string> _blogPostRepository; //TODO: Should not be needed to string
|
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
|
||||
|
public BlogPostLister(IQueryableRepository<BlogPost, string> blogPostRepository, IUnitOfWorkManager unitOfWorkManager) |
||||
|
{ |
||||
|
_blogPostRepository = blogPostRepository; |
||||
|
_unitOfWorkManager = unitOfWorkManager; |
||||
|
} |
||||
|
|
||||
|
public void List() |
||||
|
{ |
||||
|
Console.WriteLine(); |
||||
|
Console.WriteLine("List of blog posts:"); |
||||
|
|
||||
|
using (var unitOfWork = _unitOfWorkManager.Begin()) |
||||
|
{ |
||||
|
//_blogPostRepository.Insert(new BlogPost("Hello World 3!", "Hello World 3......"));
|
||||
|
|
||||
|
foreach (var blogPost in _blogPostRepository) |
||||
|
{ |
||||
|
Console.WriteLine("# " + blogPost); |
||||
|
|
||||
|
foreach (var comment in blogPost.Comments) |
||||
|
{ |
||||
|
Console.WriteLine(" - " + comment); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
unitOfWork.Complete(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,5 +1,6 @@ |
|||||
{ |
{ |
||||
"ConnectionStrings": { |
"ConnectionStrings": { |
||||
"Default": "Server=localhost;Database=AbpDesk;Trusted_Connection=True;" |
"Default": "Server=localhost;Database=AbpDesk;Trusted_Connection=True;", |
||||
|
"AbpDeskMongoBlog": "mongodb://127.0.0.1:27017|AbpDeskBlog" |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
|
<PropertyGroup> |
||||
|
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
||||
|
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
||||
|
<PropertyGroup Label="Globals"> |
||||
|
<ProjectGuid>63244dc7-34be-44e1-bf6f-f2672e59af36</ProjectGuid> |
||||
|
<RootNamespace> |
||||
|
</RootNamespace> |
||||
|
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
||||
|
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
||||
|
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> |
||||
|
</PropertyGroup> |
||||
|
<PropertyGroup> |
||||
|
<SchemaVersion>2.0</SchemaVersion> |
||||
|
</PropertyGroup> |
||||
|
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
||||
|
</Project> |
||||
@ -0,0 +1,20 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
|
||||
|
namespace AbpDesk.Blogging |
||||
|
{ |
||||
|
[DependsOn(typeof(AbpMongoDbModule))] |
||||
|
public class AbpDeskMongoBlogModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
services.AddMongoDbContext<AbpDeskMongoDbContext>(options => |
||||
|
{ |
||||
|
options.WithDefaultRepositories(); |
||||
|
}); |
||||
|
|
||||
|
services.AddAssemblyOf<AbpDeskMongoBlogModule>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
|
||||
|
namespace AbpDesk.Blogging |
||||
|
{ |
||||
|
[ConnectionStringName(ConnectionStringName)] |
||||
|
public class AbpDeskMongoDbContext : AbpMongoDbContext |
||||
|
{ |
||||
|
public const string ConnectionStringName = "AbpDeskMongoBlog"; |
||||
|
|
||||
|
private static readonly Type[] EntityCollectionTypes = { |
||||
|
typeof(BlogPost) |
||||
|
}; |
||||
|
|
||||
|
public override IReadOnlyList<Type> GetEntityCollectionTypes() |
||||
|
{ |
||||
|
return EntityCollectionTypes; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.ExtensionMethods; |
||||
|
|
||||
|
namespace AbpDesk.Blogging |
||||
|
{ |
||||
|
public class BlogPost : AggregateRoot |
||||
|
{ |
||||
|
public virtual string Title { get; protected set; } |
||||
|
|
||||
|
public virtual string Body { get; protected set; } |
||||
|
|
||||
|
public virtual ICollection<BlogPostComment> Comments { get; protected set; } |
||||
|
|
||||
|
protected BlogPost() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public BlogPost([NotNull] string title, [NotNull] string body) |
||||
|
{ |
||||
|
Id = Guid.NewGuid().ToString("D"); |
||||
|
|
||||
|
Check.NotNull(title, nameof(title)); |
||||
|
Check.NotNull(body, nameof(body)); |
||||
|
|
||||
|
Title = title; |
||||
|
Body = body; |
||||
|
|
||||
|
Comments = new List<BlogPostComment>(); |
||||
|
} |
||||
|
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
return $"{base.ToString()}, Title = {Title}, Body = {Body.TruncateWithPostfix(32)}"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
|
||||
|
namespace AbpDesk.Blogging |
||||
|
{ |
||||
|
public class BlogPostComment : Entity |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public virtual string Name { get; protected set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public virtual string Email { get; protected set; } |
||||
|
|
||||
|
public virtual byte? Star { get; protected set; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public virtual string Message { get; protected set; } |
||||
|
|
||||
|
public BlogPostComment() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public BlogPostComment(string name, string message, string email = null, byte? star = null) |
||||
|
{ |
||||
|
Name = name; |
||||
|
Email = email; |
||||
|
Message = message; |
||||
|
Star = star; |
||||
|
} |
||||
|
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
return $"{base.ToString()}, " + |
||||
|
$"Name = {Name}, " + |
||||
|
$"Email = {Email}, " + |
||||
|
$"Message = {Message}, " + |
||||
|
$"Star = {(Star.HasValue ? Star.Value.ToString() : "none")}"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System.Reflection; |
||||
|
using System.Runtime.CompilerServices; |
||||
|
using System.Runtime.InteropServices; |
||||
|
|
||||
|
// General Information about an assembly is controlled through the following
|
||||
|
// set of attributes. Change these attribute values to modify the information
|
||||
|
// associated with an assembly.
|
||||
|
[assembly: AssemblyConfiguration("")] |
||||
|
[assembly: AssemblyCompany("")] |
||||
|
[assembly: AssemblyProduct("AbpDesk.MongoBlog")] |
||||
|
[assembly: AssemblyTrademark("")] |
||||
|
|
||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
|
// to COM components. If you need to access a type in this assembly from
|
||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||
|
[assembly: ComVisible(false)] |
||||
|
|
||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
|
[assembly: Guid("63244dc7-34be-44e1-bf6f-f2672e59af36")] |
||||
@ -0,0 +1,15 @@ |
|||||
|
{ |
||||
|
"version": "1.0.0-*", |
||||
|
|
||||
|
"dependencies": { |
||||
|
"NETStandard.Library": "1.6.1", |
||||
|
"Volo.Abp": "1.0.0-*", |
||||
|
"Volo.Abp.MongoDB": "1.0.0-*" |
||||
|
}, |
||||
|
|
||||
|
"frameworks": { |
||||
|
"netstandard1.6": { |
||||
|
"imports": "dnxcore50" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public class AbpDbContextRegistrationOptions : CommonDbContextRegistrationOptions, IAbpDbContextRegistrationOptionsBuilder |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -1,57 +0,0 @@ |
|||||
using System; |
|
||||
using Volo.Abp; |
|
||||
using Volo.Abp.Domain.Entities; |
|
||||
using Volo.Abp.Domain.Repositories; |
|
||||
using Volo.Abp.Reflection; |
|
||||
|
|
||||
namespace Microsoft.Extensions.DependencyInjection |
|
||||
{ |
|
||||
public class AddAbpDbContextOptions |
|
||||
{ |
|
||||
internal RepositoryRegistrationOptions RepositoryOptions { get; set; } |
|
||||
|
|
||||
public AddAbpDbContextOptions() |
|
||||
{ |
|
||||
RepositoryOptions = new RepositoryRegistrationOptions(); |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Registers default repositories for this DbContext.
|
|
||||
/// </summary>
|
|
||||
/// <param name="includeAllEntities">
|
|
||||
/// Registers repositories only for aggregate root entities by default.
|
|
||||
/// set <see cref="includeAllEntities"/> to true to include all entities.
|
|
||||
/// </param>
|
|
||||
public void WithDefaultRepositories(bool includeAllEntities = false) |
|
||||
{ |
|
||||
RepositoryOptions.RegisterDefaultRepositories = true; |
|
||||
RepositoryOptions.IncludeAllEntitiesForDefaultRepositories = includeAllEntities; |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Registers custom repository for a specific entity.
|
|
||||
/// Custom repositories overrides default repositories.
|
|
||||
/// </summary>
|
|
||||
/// <typeparam name="TEntity">Entity type</typeparam>
|
|
||||
/// <typeparam name="TRepository">Repository type</typeparam>
|
|
||||
public void WithCustomRepository<TEntity, TRepository>() |
|
||||
{ |
|
||||
WithCustomRepository(typeof(TEntity), typeof(TRepository)); |
|
||||
} |
|
||||
|
|
||||
private void WithCustomRepository(Type entityType, Type repositoryType) |
|
||||
{ |
|
||||
if (!ReflectionHelper.IsAssignableToGenericType(entityType, typeof(IEntity<>))) |
|
||||
{ |
|
||||
throw new AbpException($"Given entityType is not an entity: {entityType.AssemblyQualifiedName}. It must implement {typeof(IEntity<>).AssemblyQualifiedName}."); |
|
||||
} |
|
||||
|
|
||||
if (!ReflectionHelper.IsAssignableToGenericType(repositoryType, typeof(IRepository<,>))) |
|
||||
{ |
|
||||
throw new AbpException($"Given repositoryType is not a repository: {entityType.AssemblyQualifiedName}. It must implement {typeof(IRepository<,>).AssemblyQualifiedName}."); |
|
||||
} |
|
||||
|
|
||||
RepositoryOptions.CustomRepositories[entityType] = repositoryType; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public interface IAbpDbContextRegistrationOptionsBuilder : ICommonDbContextRegistrationOptionsBuilder |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -1,19 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace Microsoft.Extensions.DependencyInjection |
|
||||
{ |
|
||||
internal class RepositoryRegistrationOptions |
|
||||
{ |
|
||||
public bool RegisterDefaultRepositories { get; set; } |
|
||||
|
|
||||
public bool IncludeAllEntitiesForDefaultRepositories { get; set; } |
|
||||
|
|
||||
public Dictionary<Type, Type> CustomRepositories { get; set; } |
|
||||
|
|
||||
public RepositoryRegistrationOptions() |
|
||||
{ |
|
||||
CustomRepositories = new Dictionary<Type, Type>(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,60 @@ |
|||||
|
using System; |
||||
|
using System.Reflection; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Domain.Repositories.MongoDB; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public static class AbpMongoDbServiceCollectionExtensions |
||||
|
{ |
||||
|
public static IServiceCollection AddMongoDbContext<TMongoDbContext>(this IServiceCollection services, Action<IMongoDbContextRegistrationOptionsBuilder> optionsBuilder = null) //Created overload instead of default parameter
|
||||
|
where TMongoDbContext : AbpMongoDbContext |
||||
|
{ |
||||
|
var options = new MongoDbContextRegistrationOptions(); |
||||
|
optionsBuilder?.Invoke(options); |
||||
|
|
||||
|
AddRepositories<TMongoDbContext>(services, options); |
||||
|
|
||||
|
return services; |
||||
|
} |
||||
|
|
||||
|
private static void AddRepositories<TMongoDbContext>(IServiceCollection services, MongoDbContextRegistrationOptions options) |
||||
|
where TMongoDbContext : AbpMongoDbContext |
||||
|
{ |
||||
|
foreach (var customRepository in options.CustomRepositories) |
||||
|
{ |
||||
|
services.AddDefaultRepository(customRepository.Key, customRepository.Value); |
||||
|
} |
||||
|
|
||||
|
if (options.RegisterDefaultRepositories) |
||||
|
{ |
||||
|
RegisterDefaultRepositories(services, typeof(TMongoDbContext), options); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static void RegisterDefaultRepositories(IServiceCollection services, Type dbContextType, MongoDbContextRegistrationOptions options) |
||||
|
{ |
||||
|
var mongoDbContext = (AbpMongoDbContext) Activator.CreateInstance(dbContextType); |
||||
|
|
||||
|
foreach (var entityType in mongoDbContext.GetEntityCollectionTypes()) |
||||
|
{ |
||||
|
if (!options.ShouldRegisterDefaultRepositoryFor(entityType)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
RegisterDefaultRepository(services, dbContextType, entityType, options); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static void RegisterDefaultRepository(IServiceCollection services, Type dbContextType, Type entityType, MongoDbContextRegistrationOptions options) |
||||
|
{ |
||||
|
var repositoryImplementationType = typeof(IEntity).GetTypeInfo().IsAssignableFrom(entityType) |
||||
|
? typeof(MongoDbRepository<,>).MakeGenericType(dbContextType, entityType) |
||||
|
: typeof(MongoDbRepository<,,>).MakeGenericType(dbContextType, entityType, EntityHelper.GetPrimaryKeyType(entityType)); |
||||
|
|
||||
|
services.AddDefaultRepository(entityType, repositoryImplementationType); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public interface IMongoDbContextRegistrationOptionsBuilder : ICommonDbContextRegistrationOptionsBuilder |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public class MongoDbContextRegistrationOptions : CommonDbContextRegistrationOptions, IMongoDbContextRegistrationOptionsBuilder |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace Volo.Abp.MongoDB |
||||
|
{ |
||||
|
public abstract class AbpMongoDbContext |
||||
|
{ |
||||
|
private static readonly Type[] EmptyTypeList = new Type[0]; |
||||
|
|
||||
|
public virtual IReadOnlyList<Type> GetEntityCollectionTypes() |
||||
|
{ |
||||
|
return EmptyTypeList; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Uow.MongoDB; |
||||
|
|
||||
|
namespace Volo.Abp.MongoDB |
||||
|
{ |
||||
|
public class AbpMongoDbModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(IServiceCollection services) |
||||
|
{ |
||||
|
//TODO: ServiceCollection extensions to register mongodbcontext!
|
||||
|
|
||||
|
services.TryAddTransient(typeof(IMongoDatabaseProvider<>), typeof(UnitOfWorkMongoDatabaseProvider<>)); |
||||
|
services.AddAssemblyOf<AbpMongoDbModule>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using MongoDB.Driver; |
||||
|
|
||||
|
namespace Volo.Abp.MongoDB |
||||
|
{ |
||||
|
public interface IMongoDatabaseProvider<TMongoDbContext> |
||||
|
where TMongoDbContext : AbpMongoDbContext |
||||
|
{ |
||||
|
IMongoDatabase GetDatabase(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using MongoDB.Driver; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.MongoDB; |
||||
|
|
||||
|
namespace Volo.Abp.Uow.MongoDB |
||||
|
{ |
||||
|
public class UnitOfWorkMongoDatabaseProvider<TMongoDbContext> : IMongoDatabaseProvider<TMongoDbContext> |
||||
|
where TMongoDbContext : AbpMongoDbContext |
||||
|
{ |
||||
|
private readonly IUnitOfWorkManager _unitOfWorkManager; |
||||
|
private readonly IConnectionStringResolver _connectionStringResolver; |
||||
|
|
||||
|
public UnitOfWorkMongoDatabaseProvider( |
||||
|
IUnitOfWorkManager unitOfWorkManager, |
||||
|
IConnectionStringResolver connectionStringResolver) |
||||
|
{ |
||||
|
_unitOfWorkManager = unitOfWorkManager; |
||||
|
_connectionStringResolver = connectionStringResolver; |
||||
|
} |
||||
|
|
||||
|
public IMongoDatabase GetDatabase() |
||||
|
{ |
||||
|
var unitOfWork = _unitOfWorkManager.Current; |
||||
|
if (unitOfWork == null) |
||||
|
{ |
||||
|
throw new AbpException("A IMongoDatabase instance can only be created inside a unit of work!"); |
||||
|
} |
||||
|
|
||||
|
var connectionString = _connectionStringResolver.Resolve<TMongoDbContext>(); |
||||
|
var dbContextKey = $"{typeof(TMongoDbContext).FullName}_{connectionString}"; |
||||
|
|
||||
|
string databaseName; |
||||
|
if (connectionString.Contains("|")) |
||||
|
{ |
||||
|
var splitted = connectionString.Split('|'); |
||||
|
connectionString = splitted[0]; |
||||
|
databaseName = splitted[1]; |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
databaseName = ConnectionStringNameAttribute.GetConnStringName<TMongoDbContext>(); |
||||
|
} |
||||
|
|
||||
|
//TODO: Create only single MongoDbClient per connection string in an application (extract MongoClientCache for example).
|
||||
|
var databaseApi = unitOfWork.GetOrAddDatabaseApi( |
||||
|
dbContextKey, |
||||
|
() => new MongoDbDatabaseApi( |
||||
|
new MongoClient(connectionString).GetDatabase(databaseName) |
||||
|
)); |
||||
|
|
||||
|
return ((MongoDbDatabaseApi)databaseApi).Database; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,69 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public class CommonDbContextRegistrationOptions : ICommonDbContextRegistrationOptionsBuilder |
||||
|
{ |
||||
|
public bool RegisterDefaultRepositories { get; set; } |
||||
|
|
||||
|
public bool IncludeAllEntitiesForDefaultRepositories { get; set; } |
||||
|
|
||||
|
public Dictionary<Type, Type> CustomRepositories { get; set; } |
||||
|
|
||||
|
public CommonDbContextRegistrationOptions() |
||||
|
{ |
||||
|
CustomRepositories = new Dictionary<Type, Type>(); |
||||
|
} |
||||
|
|
||||
|
public void WithDefaultRepositories(bool includeAllEntities = false) |
||||
|
{ |
||||
|
RegisterDefaultRepositories = true; |
||||
|
IncludeAllEntitiesForDefaultRepositories = includeAllEntities; |
||||
|
} |
||||
|
|
||||
|
public void WithCustomRepository<TEntity, TRepository>() |
||||
|
{ |
||||
|
WithCustomRepository(typeof(TEntity), typeof(TRepository)); |
||||
|
} |
||||
|
|
||||
|
private void WithCustomRepository(Type entityType, Type repositoryType) |
||||
|
{ |
||||
|
if (!ReflectionHelper.IsAssignableToGenericType(entityType, typeof(IEntity<>))) |
||||
|
{ |
||||
|
throw new AbpException($"Given entityType is not an entity: {entityType.AssemblyQualifiedName}. It must implement {typeof(IEntity<>).AssemblyQualifiedName}."); |
||||
|
} |
||||
|
|
||||
|
if (!ReflectionHelper.IsAssignableToGenericType(repositoryType, typeof(IRepository<,>))) |
||||
|
{ |
||||
|
throw new AbpException($"Given repositoryType is not a repository: {entityType.AssemblyQualifiedName}. It must implement {typeof(IRepository<,>).AssemblyQualifiedName}."); |
||||
|
} |
||||
|
|
||||
|
CustomRepositories[entityType] = repositoryType; |
||||
|
} |
||||
|
|
||||
|
public bool ShouldRegisterDefaultRepositoryFor(Type entityType) |
||||
|
{ |
||||
|
if (!RegisterDefaultRepositories) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (CustomRepositories.ContainsKey(entityType)) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
if (!IncludeAllEntitiesForDefaultRepositories && !ReflectionHelper.IsAssignableToGenericType(entityType, typeof(IAggregateRoot<>))) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public interface ICommonDbContextRegistrationOptionsBuilder |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Registers default repositories for this DbContext.
|
||||
|
/// </summary>
|
||||
|
/// <param name="includeAllEntities">
|
||||
|
/// Registers repositories only for aggregate root entities by default.
|
||||
|
/// set <see cref="includeAllEntities"/> to true to include all entities.
|
||||
|
/// </param>
|
||||
|
void WithDefaultRepositories(bool includeAllEntities = false); |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Registers custom repository for a specific entity.
|
||||
|
/// Custom repositories overrides default repositories.
|
||||
|
/// </summary>
|
||||
|
/// <typeparam name="TEntity">Entity type</typeparam>
|
||||
|
/// <typeparam name="TRepository">Repository type</typeparam>
|
||||
|
void WithCustomRepository<TEntity, TRepository>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
using System; |
||||
|
using System.Reflection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
using Volo.Abp.Reflection; |
||||
|
|
||||
|
namespace Microsoft.Extensions.DependencyInjection |
||||
|
{ |
||||
|
public static class ServiceCollectionRepositoryExtensions |
||||
|
{ |
||||
|
//TODO: validate repository and entity if they match!
|
||||
|
|
||||
|
public static void AddDefaultRepository(this IServiceCollection services, Type entityType, Type repositoryImplementationType) |
||||
|
{ |
||||
|
var primaryKeyType = EntityHelper.GetPrimaryKeyType(entityType); |
||||
|
|
||||
|
services.TryAddTransient( |
||||
|
typeof(IRepository<,>).MakeGenericType(entityType, primaryKeyType), |
||||
|
repositoryImplementationType |
||||
|
); |
||||
|
|
||||
|
services.TryAddTransient( //TODO: May not support IQueryableRepository
|
||||
|
typeof(IQueryableRepository<,>).MakeGenericType(entityType, primaryKeyType), |
||||
|
repositoryImplementationType |
||||
|
); |
||||
|
|
||||
|
if (BothSupportsDefaultPrimaryKey(entityType, repositoryImplementationType)) |
||||
|
{ |
||||
|
services.TryAddTransient( |
||||
|
typeof(IRepository<>).MakeGenericType(entityType), |
||||
|
repositoryImplementationType |
||||
|
); |
||||
|
|
||||
|
services.TryAddTransient( //TODO: May not support IQueryableRepository
|
||||
|
typeof(IQueryableRepository<>).MakeGenericType(entityType), |
||||
|
repositoryImplementationType |
||||
|
); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private static bool BothSupportsDefaultPrimaryKey(Type entityType, Type repositoryImplementationType) |
||||
|
{ |
||||
|
return typeof(IEntity).GetTypeInfo().IsAssignableFrom(entityType) && |
||||
|
ReflectionHelper.IsAssignableToGenericType(repositoryImplementationType, typeof(IRepository<>)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using System.Threading; |
||||
|
using Volo.DependencyInjection; |
||||
|
|
||||
|
namespace Volo.Abp.Uow |
||||
|
{ |
||||
|
[ExposeServices(typeof(IAmbientUnitOfWork), typeof(IUnitOfWorkAccessor))] |
||||
|
public class AmbientUnitOfWork : IAmbientUnitOfWork, ISingletonDependency |
||||
|
{ |
||||
|
public IUnitOfWork UnitOfWork => _currentUowInfo.Value; |
||||
|
|
||||
|
private readonly AsyncLocal<IUnitOfWork> _currentUowInfo; |
||||
|
|
||||
|
public AmbientUnitOfWork() |
||||
|
{ |
||||
|
_currentUowInfo = new AsyncLocal<IUnitOfWork>(); |
||||
|
} |
||||
|
|
||||
|
public void SetUnitOfWork(IUnitOfWork unitOfWork) |
||||
|
{ |
||||
|
_currentUowInfo.Value = unitOfWork; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Uow |
||||
|
{ |
||||
|
public interface IAmbientUnitOfWork : IUnitOfWorkAccessor |
||||
|
{ |
||||
|
void SetUnitOfWork([CanBeNull] IUnitOfWork unitOfWork); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
|
||||
|
namespace Volo.Abp.Uow |
||||
|
{ |
||||
|
public interface IUnitOfWorkAccessor |
||||
|
{ |
||||
|
[CanBeNull] |
||||
|
IUnitOfWork UnitOfWork { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Threading; |
||||
|
using JetBrains.Annotations; |
||||
|
using Volo.Abp.Threading; |
||||
|
|
||||
|
namespace Volo.Abp.Uow |
||||
|
{ |
||||
|
public static class UnitOfWorkExtensions |
||||
|
{ |
||||
|
//TODO: Implement all sync versions
|
||||
|
|
||||
|
public static void Complete([NotNull] this IUnitOfWork unitOfWork, CancellationToken cancellationToken = default(CancellationToken)) |
||||
|
{ |
||||
|
Check.NotNull(unitOfWork, nameof(unitOfWork)); |
||||
|
|
||||
|
AsyncHelper.RunSync(() => unitOfWork.CompleteAsync(cancellationToken)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue