Skip to content

Commit fd62ba8

Browse files
authored
Merge pull request #114 from Royal-Code/detached
muitas alterações
2 parents 40d5bd0 + a09d969 commit fd62ba8

File tree

4 files changed

+203
-6
lines changed

4 files changed

+203
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace RoyalCode.WorkContext.Abstractions;
2+
3+
/// <summary>
4+
/// Used for components that work with service providers in their infrastructure and can share the services they provide.
5+
/// </summary>
6+
public interface IInfrastructureProvidesServices
7+
{
8+
/// <summary>
9+
/// Gets the service object of the specified type.
10+
/// </summary>
11+
/// <param name="serviceType">An object that specifies the type of service object to get.</param>
12+
/// <returns>
13+
/// A service object of type <paramref name="serviceType" />.
14+
/// </returns>
15+
/// <exception cref="InvalidOperationException">
16+
/// If the service provider is not provided and it was not found in the database context.
17+
/// </exception>
18+
object GetService(Type serviceType);
19+
20+
/// <summary>
21+
/// Gets the service object of the specified type.
22+
/// </summary>
23+
/// <typeparam name="T">The type of service object to get.</typeparam>
24+
/// <returns>
25+
/// A service object of type <typeparam name="T"></typeparam>.
26+
/// </returns>
27+
/// <exception cref="InvalidOperationException">
28+
/// If the service provider is not provided and it was not found in the database context.
29+
/// </exception>
30+
T GetService<T>();
31+
}

RoyalCode.EnterprisePatterns/RoyalCode.WorkContext.Abstractions/IWorkContext.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ namespace RoyalCode.WorkContext.Abstractions;
2525
/// and the services that are provided is part of the persistence unit.
2626
/// </para>
2727
/// </summary>
28-
public interface IWorkContext : IUnitOfWork, IEntityManager, ISearchable, IHintsContainer { }
28+
public interface IWorkContext : IUnitOfWork, IEntityManager, ISearchable, IHintsContainer, IInfrastructureProvidesServices { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
namespace RoyalCode.WorkContext.Abstractions;
2+
3+
/// <summary>
4+
/// Extensions methods for <see cref="IWorkContext"/>.
5+
/// </summary>
6+
public static class WorkContextExtensions
7+
{
8+
/// <summary>
9+
/// <para>
10+
/// Adds a new entity to the repository to be persisted.
11+
/// </para>
12+
/// </summary>
13+
/// <param name="context">The work context to get the repository.</param>
14+
/// <param name="entity">The new entity instance.</param>
15+
public static void Add<TEntity>(this IWorkContext context, TEntity entity)
16+
where TEntity : class
17+
=> context.Repository<TEntity>().Add(entity);
18+
19+
/// <summary>
20+
/// <para>
21+
/// Adds a collection of new entities to the repository to be persisted.
22+
/// </para>
23+
/// </summary>
24+
/// <param name="context">The work context to get the repository.</param>
25+
/// <param name="entities">A collection of new entities.</param>
26+
public static void AddRange<TEntity>(this IWorkContext context, IEnumerable<TEntity> entities)
27+
where TEntity : class
28+
=> context.Repository<TEntity>().AddRange(entities);
29+
30+
/// <summary>
31+
/// <para>
32+
/// Finds an existing entity through its unique identity (id).
33+
/// </para>
34+
/// </summary>
35+
/// <param name="context">The work context to get the repository.</param>
36+
/// <param name="id">The entity identity.</param>
37+
/// <returns>
38+
/// <para>
39+
/// Existing instance, or null/default if it does not exist.
40+
/// </para>
41+
/// </returns>
42+
public static TEntity? Find<TEntity>(this IWorkContext context, object id)
43+
where TEntity : class
44+
=> context.Repository<TEntity>().Find(id);
45+
46+
/// <summary>
47+
/// <para>
48+
/// Finds an existing entity through its unique identity (id).
49+
/// </para>
50+
/// </summary>
51+
/// <param name="context">The work context to get the repository.</param>
52+
/// <param name="id">The entity identity.</param>
53+
/// <param name="token">Token for cancelling tasks.</param>
54+
/// <returns>
55+
/// <para>
56+
/// Existing instance, or null/default if it does not exist.
57+
/// </para>
58+
/// </returns>
59+
public static ValueTask<TEntity?> FindAsync<TEntity>(this IWorkContext context, object id, CancellationToken token = default)
60+
where TEntity : class
61+
=> context.Repository<TEntity>().FindAsync(id, token);
62+
63+
/// <summary>
64+
/// <para>
65+
/// Remove an entity from the database.
66+
/// </para>
67+
/// </summary>
68+
/// <param name="context">The work context to get the repository.</param>
69+
/// <param name="entity">The entity.</param>
70+
public static void Remove<TEntity>(this IWorkContext context,TEntity entity)
71+
where TEntity : class
72+
=> context.Repository<TEntity>().Remove(entity);
73+
74+
/// <summary>
75+
/// <para>
76+
/// Remove a range of entities from the database.
77+
/// </para>
78+
/// </summary>
79+
/// <param name="context">The work context to get the repository.</param>
80+
/// <param name="entities">The entities.</param>
81+
/// <exception cref="ArgumentNullException">
82+
/// If <paramref name="entities"/> is null.
83+
/// </exception>
84+
public static void RemoveRange<TEntity>(this IWorkContext context, IEnumerable<TEntity> entities)
85+
where TEntity : class
86+
=> context.Repository<TEntity>().RemoveRange(entities);
87+
88+
/// <summary>
89+
/// <para>
90+
/// Delete the entity by its Id.
91+
/// </para>
92+
/// </summary>
93+
/// <param name="context">The work context to get the repository.</param>
94+
/// <param name="id">The entity id.</param>
95+
/// <returns>
96+
/// <para>
97+
/// The entity excluded, or null if the entity is not found.
98+
/// </para>
99+
/// </returns>
100+
public static TEntity? Delete<TEntity>(this IWorkContext context, object id)
101+
where TEntity : class
102+
=> context.Repository<TEntity>().Delete(id);
103+
104+
/// <summary>
105+
/// <para>
106+
/// Delete a range of entities by their Ids.
107+
/// </para>
108+
/// </summary>
109+
/// <param name="context">The work context to get the repository.</param>
110+
/// <param name="ids">The entities Ids.</param>
111+
/// <returns>
112+
/// <para>
113+
/// The entities excluded, or null if the entity is not found.
114+
/// </para>
115+
/// </returns>
116+
public static IEnumerable<TEntity?> DeleteRange<TEntity>(this IWorkContext context, IEnumerable<object> ids)
117+
where TEntity : class
118+
=> context.Repository<TEntity>().DeleteRange(ids);
119+
120+
/// <summary>
121+
/// <para>
122+
/// Delete the entity by their Id.
123+
/// </para>
124+
/// </summary>
125+
/// <param name="context">The work context to get the repository.</param>
126+
/// <param name="id">The entity Id.</param>
127+
/// <param name="token">Token for cancelling tasks.</param>
128+
/// <returns>
129+
/// <para>
130+
/// The entity excluded, or null if the entity is not found.
131+
/// </para>
132+
/// </returns>
133+
public static Task<TEntity?> DeleteAsync<TEntity>(this IWorkContext context, object id, CancellationToken token = default)
134+
where TEntity : class
135+
=> context.Repository<TEntity>().DeleteAsync(id, token);
136+
137+
/// <summary>
138+
/// <para>
139+
/// Delete a range of entities by their Ids.
140+
/// </para>
141+
/// </summary>
142+
/// <param name="context">The work context to get the repository.</param>
143+
/// <param name="ids">The entities Ids.</param>
144+
/// <param name="token">Token for cancelling tasks.</param>
145+
/// <returns>
146+
/// <para>
147+
/// The entities excluded, or null if the entity is not found.
148+
/// </para>
149+
/// </returns>
150+
public static Task<IEnumerable<TEntity?>> DeleteRangeAsync<TEntity>(
151+
this IWorkContext context, IEnumerable<object> ids, CancellationToken token = default)
152+
where TEntity : class
153+
=> context.Repository<TEntity>().DeleteRangeAsync(ids, token);
154+
}

RoyalCode.EnterprisePatterns/RoyalCode.WorkContext.EntityFramework/WorkContext.cs

+17-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.EntityFrameworkCore;
2+
using Microsoft.EntityFrameworkCore.Infrastructure;
23
using Microsoft.Extensions.DependencyInjection;
34
using RoyalCode.OperationHint.Abstractions;
45
using RoyalCode.Repositories.EntityFramework;
@@ -24,9 +25,13 @@ public class WorkContext<TDbContext> : UnitOfWork<TDbContext>, IWorkContext
2425
/// </summary>
2526
/// <param name="db">The database context.</param>
2627
/// <param name="serviceProvider">The service provider.</param>
27-
public WorkContext(TDbContext db, IServiceProvider serviceProvider) : base(db)
28+
public WorkContext(TDbContext db, IServiceProvider? serviceProvider = null) : base(db)
2829
{
29-
this.serviceProvider = serviceProvider;
30+
this.serviceProvider = serviceProvider
31+
?? db.GetService<IDbContextOptions>()
32+
.Extensions.OfType<CoreOptionsExtension>().FirstOrDefault()
33+
?.ApplicationServiceProvider
34+
?? throw new InvalidOperationException("The service provider was not provided and it was not found in the database context");
3035
}
3136

3237
/// <inheritdoc />
@@ -41,7 +46,7 @@ public IAllEntities<TEntity> All<TEntity>() where TEntity : class
4146
{
4247
var search = serviceProvider.GetService<Searches.Persistence.EntityFramework.Internals.IAllEntities<TDbContext, TEntity>>();
4348
return search is null
44-
? throw new InvalidOperationException($"The search for all the entities of type {typeof(TEntity)} was not configured for the unit of work")
49+
? throw new InvalidOperationException($"The search for all the entities of type {typeof(TEntity)} was not configured for the work context")
4550
: (IAllEntities<TEntity>)search;
4651
}
4752

@@ -50,7 +55,7 @@ public ISearch<TEntity> CreateSearch<TEntity>() where TEntity : class
5055
{
5156
var search = serviceProvider.GetService<Searches.Persistence.EntityFramework.Internals.ISearch<TDbContext, TEntity>>();
5257
return search is null
53-
? throw new InvalidOperationException($"The search for the entity type {typeof(TEntity)} was not configured for the unit of work")
58+
? throw new InvalidOperationException($"The search for the entity type {typeof(TEntity)} was not configured for the work context")
5459
: (ISearch<TEntity>)search;
5560
}
5661

@@ -59,7 +64,14 @@ public IRepository<TEntity> Repository<TEntity>() where TEntity : class
5964
{
6065
var repository = serviceProvider.GetService<IRepository<TDbContext, TEntity>>();
6166
return repository is null
62-
? throw new InvalidOperationException($"The repository for the entity type {typeof(TEntity)} was not configured for the unit of work")
67+
? throw new InvalidOperationException($"The repository for the entity type {typeof(TEntity)} was not configured for the work context")
6368
: (IRepository<TEntity>)repository;
6469
}
70+
71+
/// <inheritdoc />
72+
public object GetService(Type serviceType) => serviceProvider.GetService(serviceType)
73+
?? throw new InvalidOperationException($"The service of type {serviceType} was not found in the service provider of the work context");
74+
75+
/// <inheritdoc />
76+
public TService GetService<TService>() => (TService)GetService(typeof(TService));
6577
}

0 commit comments

Comments
 (0)