diff --git a/.github/workflows/build-test.yaml b/.github/workflows/build-test.yaml index bd82dd6..f23a063 100644 --- a/.github/workflows/build-test.yaml +++ b/.github/workflows/build-test.yaml @@ -26,11 +26,11 @@ jobs: with: fetch-depth: 0 - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x 8.0.x + 9.0.x - name: Restore run: dotnet restore - name: Build @@ -47,12 +47,12 @@ jobs: # - name: Upload artifacts if: matrix.os == 'ubuntu-latest' - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: artifacts path: ./artifacts - name: Upload test results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: test-results-${{ matrix.os }} path: ./test-results @@ -66,13 +66,13 @@ jobs: name: Deploy Testing steps: - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x 8.0.x + 9.0.x - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: artifacts path: ./artifacts @@ -89,13 +89,13 @@ jobs: name: Deploy Production steps: - name: Setup .NET - uses: actions/setup-dotnet@v3 + uses: actions/setup-dotnet@v4 with: dotnet-version: | - 6.0.x 8.0.x + 9.0.x - name: Download artifacts - uses: actions/download-artifact@v3 + uses: actions/download-artifact@v4 with: name: artifacts path: ./artifacts diff --git a/AppCoreNet.Data.sln b/AppCoreNet.Data.sln index b93b204..f1629a1 100644 --- a/AppCoreNet.Data.sln +++ b/AppCoreNet.Data.sln @@ -25,6 +25,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution LICENSE = LICENSE README.md = README.md stylecop.json = stylecop.json + Directory.Packages.props = Directory.Packages.props + NuGet.config = NuGet.config + renovate.json = renovate.json EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{80A494A8-C591-4A8D-98DF-826D2D32ECA9}" diff --git a/Directory.Build.props b/Directory.Build.props index 02944da..b72f0ae 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -23,7 +23,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -38,7 +38,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -47,6 +47,7 @@ true + true $(MSBuildThisFileDirectory)AppCoreNet.ruleset @@ -55,19 +56,15 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Directory.Packages.props b/Directory.Packages.props new file mode 100644 index 0000000..3759974 --- /dev/null +++ b/Directory.Packages.props @@ -0,0 +1,33 @@ + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/GitVersion.yml b/GitVersion.yml index 54ab19b..7a5d928 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -1,12 +1,13 @@ +workflow: GitFlow/v1 +mode: ContinuousDelivery assembly-versioning-scheme: Major assembly-file-versioning-scheme: MajorMinorPatchTag assembly-informational-format: '{SemVer}+{ShortSha}' -continuous-delivery-fallback-tag: 'alpha' -mode: 'ContinuousDeployment' branches: main: + label: alpha increment: Minor + support: + label: alpha pull-request: - tag: 'pr' -ignore: - sha: [] + label: pr diff --git a/NuGet.config b/NuGet.config new file mode 100644 index 0000000..603adb2 --- /dev/null +++ b/NuGet.config @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/global.json b/global.json index da113e4..498023d 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.0", + "version": "9.0.300", "rollForward": "latestFeature", "allowPrerelease": false } diff --git a/renovate.json b/renovate.json new file mode 100644 index 0000000..53b277a --- /dev/null +++ b/renovate.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://docs.renovatebot.com/renovate-schema.json", + "extends": [ + "config:recommended" + ], + "packageRules": [ + { + "groupName": "AppCoreNet.Shared", + "matchSourceUrls": [ + "https://github.com/AppCoreNet/Shared" + ] + }, + { + "groupName": "AppCoreNet.Extensions", + "matchSourceUrls": [ + "https://github.com/AppCoreNet/Extensions" + ] + } + ] +} \ No newline at end of file diff --git a/src/AppCoreNet.Data.Abstractions/AppCoreNet.Data.Abstractions.csproj b/src/AppCoreNet.Data.Abstractions/AppCoreNet.Data.Abstractions.csproj index 4917fe7..eb47262 100644 --- a/src/AppCoreNet.Data.Abstractions/AppCoreNet.Data.Abstractions.csproj +++ b/src/AppCoreNet.Data.Abstractions/AppCoreNet.Data.Abstractions.csproj @@ -1,13 +1,13 @@ - netstandard2.1;netstandard2.0;net462 + net8.0;netstandard2.1;netstandard2.0;net462 AppCoreNet.Data Provides public API for the AppCore .NET persistence framework. - + \ No newline at end of file diff --git a/src/AppCoreNet.Data.Abstractions/EntityExtensions.cs b/src/AppCoreNet.Data.Abstractions/EntityExtensions.cs index 29f45f1..45e50d3 100644 --- a/src/AppCoreNet.Data.Abstractions/EntityExtensions.cs +++ b/src/AppCoreNet.Data.Abstractions/EntityExtensions.cs @@ -16,7 +16,7 @@ public static class EntityExtensions /// /// The type of the entity id. /// The entity. - /// tru if the entity is transient; false otherwise. + /// true if the entity is transient; false otherwise. public static bool IsTransient(this IEntity entity) { Ensure.Arg.NotNull(entity); diff --git a/src/AppCoreNet.Data.AutoMapper/AppCoreNet.Data.AutoMapper.csproj b/src/AppCoreNet.Data.AutoMapper/AppCoreNet.Data.AutoMapper.csproj index 6639c06..0ed598d 100644 --- a/src/AppCoreNet.Data.AutoMapper/AppCoreNet.Data.AutoMapper.csproj +++ b/src/AppCoreNet.Data.AutoMapper/AppCoreNet.Data.AutoMapper.csproj @@ -1,20 +1,12 @@  - net6.0;netstandard2.1;netstandard2.0;net462 + net8.0 Adds AutoMapper support to AppCore .NET persistence. - - - - - - - - - - + + diff --git a/src/AppCoreNet.Data.AutoMapper/AutoMapperDataProviderBuilderExtensions.cs b/src/AppCoreNet.Data.AutoMapper/AutoMapperDataProviderBuilderExtensions.cs index 4519b62..dcb025e 100644 --- a/src/AppCoreNet.Data.AutoMapper/AutoMapperDataProviderBuilderExtensions.cs +++ b/src/AppCoreNet.Data.AutoMapper/AutoMapperDataProviderBuilderExtensions.cs @@ -22,9 +22,12 @@ public static class AutoMapperDataProviderBuilderExtensions /// /// The . /// The delegate used to configure AutoMapper. - public static void AddAutoMapper(this IDataProviderBuilder builder, Action? config = null) + public static void AddAutoMapper( + this IDataProviderBuilder builder, + Action? config = null) { Ensure.Arg.NotNull(builder); + builder.Services.AddAutoMapper(config); builder.Services.TryAddTransient(); } diff --git a/src/AppCoreNet.Data.EntityFrameworkCore/AppCoreNet.Data.EntityFrameworkCore.csproj b/src/AppCoreNet.Data.EntityFrameworkCore/AppCoreNet.Data.EntityFrameworkCore.csproj index 431fb51..a442802 100644 --- a/src/AppCoreNet.Data.EntityFrameworkCore/AppCoreNet.Data.EntityFrameworkCore.csproj +++ b/src/AppCoreNet.Data.EntityFrameworkCore/AppCoreNet.Data.EntityFrameworkCore.csproj @@ -1,22 +1,12 @@ - net8.0;net6.0;netstandard2.0;net462 + net8.0 Adds EntityFramework Core support to AppCore .NET persistence. - - - - - - - - - - - - + + diff --git a/src/AppCoreNet.Data.EntityFrameworkCore/DbContextRepository.cs b/src/AppCoreNet.Data.EntityFrameworkCore/DbContextRepository.cs index 40dcb91..be7b7df 100644 --- a/src/AppCoreNet.Data.EntityFrameworkCore/DbContextRepository.cs +++ b/src/AppCoreNet.Data.EntityFrameworkCore/DbContextRepository.cs @@ -80,7 +80,7 @@ protected PagedQueryHandler(DbContextDataProvider provider) } } - private static readonly EntityModelProperties _entityModelProperties = new (); + private static readonly EntityModelProperties _entityModelProperties = new(); private readonly DbModelProperties _modelProperties; /// @@ -137,7 +137,7 @@ protected virtual IQueryable ApplyPrimaryKeyExpression(IQueryable EF.Property(e, primaryKeyPropertyName) !.Equals(keyValue)); + return queryable.Where(e => EF.Property(e, primaryKeyPropertyName)!.Equals(keyValue)); } for (int i = 0; i < primaryKey.Length; i++) @@ -255,17 +255,30 @@ public async Task QueryAsync( TResult result; try { - result = await DoAsync( - () => Provider.Logger.QueryExecuting(query), - async () => await queryHandler.ExecuteAsync(query, cancellationToken) - .ConfigureAwait(false), - (_, elapsedTimeMs) => Provider.Logger.QueryExecuted(query, elapsedTimeMs), - error => Provider.Logger.QueryExecuteFailed(error, query)) - .ConfigureAwait(false); + result = + await DoAsync( + () => + { + Provider.Logger.QueryExecuting(query); + }, + async () => + { + return await queryHandler.ExecuteAsync(query, cancellationToken) + .ConfigureAwait(false); + }, + (_, elapsedTimeMs) => + { + Provider.Logger.QueryExecuted(query, elapsedTimeMs); + }, + error => + { + Provider.Logger.QueryExecuteFailed(error, query); + }) + .ConfigureAwait(false); } finally { - await DisposeQueryHandler(queryHandler) + await DisposeQueryHandlerAsync(queryHandler) .ConfigureAwait(false); } @@ -277,7 +290,7 @@ await DisposeQueryHandler(queryHandler) "ReSharper", "SuspiciousTypeConversion.Global", Justification = "Handler may implement IDisposable.")] - async ValueTask DisposeQueryHandler(IDbContextQueryHandler handler) + async ValueTask DisposeQueryHandlerAsync(IDbContextQueryHandler handler) { switch (handler) { @@ -315,30 +328,37 @@ await disposable.DisposeAsync() { Ensure.Arg.NotNull(id); - TEntity? entity = await DoAsync( - () => Provider.Logger.EntityLoading(typeof(TEntity), id), - async () => - { - TDbEntity? dbEntity = await FindCoreAsync(id, cancellationToken) - .ConfigureAwait(false); - - return dbEntity != null - ? Provider.EntityMapper.Map(dbEntity) - : default; - }, - (result, elapsedTimeMs) => - { - if (result != default) + TEntity? entity = + await DoAsync( + () => { - Provider.Logger.EntityLoaded(result, elapsedTimeMs); - } - else + Provider.Logger.EntityLoading(typeof(TEntity), id); + }, + async () => { - Provider.Logger.EntityNotFound(typeof(TEntity), id); - } - }, - error => Provider.Logger.EntityLoadFailed(error, typeof(TEntity), id)) - .ConfigureAwait(false); + TDbEntity? dbEntity = await FindCoreAsync(id, cancellationToken) + .ConfigureAwait(false); + + return dbEntity != null + ? Provider.EntityMapper.Map(dbEntity) + : default; + }, + (result, elapsedTimeMs) => + { + if (result != default) + { + Provider.Logger.EntityLoaded(result, elapsedTimeMs); + } + else + { + Provider.Logger.EntityNotFound(typeof(TEntity), id); + } + }, + error => + { + Provider.Logger.EntityLoadFailed(error, typeof(TEntity), id); + }) + .ConfigureAwait(false); return entity; } @@ -377,26 +397,36 @@ public virtual async Task CreateAsync(TEntity entity, CancellationToken { Ensure.Arg.NotNull(entity); - TEntity result = await DoAsync( - () => Provider.Logger.EntityCreating(entity), - async () => - { - var dbEntity = Provider.EntityMapper.Map(entity); + TEntity result = + await DoAsync( + () => + { + Provider.Logger.EntityCreating(entity); + }, + async () => + { + var dbEntity = Provider.EntityMapper.Map(entity); - EntityEntry dbEntry = await CreateCoreAsync(entity, dbEntity, cancellationToken) - .ConfigureAwait(false); + EntityEntry dbEntry = await CreateCoreAsync(entity, dbEntity, cancellationToken) + .ConfigureAwait(false); - dbEntity = dbEntry.Entity; - UpdateChangeToken(dbEntry, entity); + dbEntity = dbEntry.Entity; + UpdateChangeToken(dbEntry, entity); - await Provider.SaveChangesAsync(cancellationToken) - .ConfigureAwait(false); + await Provider.SaveChangesAsync(cancellationToken) + .ConfigureAwait(false); - return Provider.EntityMapper.Map(dbEntity); - }, - (e, elapsedTimeMs) => Provider.Logger.EntityCreated(e, elapsedTimeMs), - error => Provider.Logger.EntityCreateFailed(error, entity)) - .ConfigureAwait(false); + return Provider.EntityMapper.Map(dbEntity); + }, + (e, elapsedTimeMs) => + { + Provider.Logger.EntityCreated(e, elapsedTimeMs); + }, + error => + { + Provider.Logger.EntityCreateFailed(error, entity); + }) + .ConfigureAwait(false); return result; } @@ -427,36 +457,46 @@ public virtual async Task UpdateAsync(TEntity entity, CancellationToken $"The entity cannot be updated because the '{nameof(IEntity.Id)}' property has the default value."); } - TEntity result = await DoAsync( - () => Provider.Logger.EntityUpdating(entity), - async () => - { - TDbEntity? dbEntity = await GetQueryable(entity.Id) - .FirstOrDefaultAsync(cancellationToken) - .ConfigureAwait(false); + TEntity result = + await DoAsync( + () => + { + Provider.Logger.EntityUpdating(entity); + }, + async () => + { + TDbEntity? dbEntity = await GetQueryable(entity.Id) + .FirstOrDefaultAsync(cancellationToken) + .ConfigureAwait(false); - if (dbEntity == null) - throw new EntityConcurrencyException(); + if (dbEntity == null) + throw new EntityConcurrencyException(); - Provider.EntityMapper.Map(entity, dbEntity); + Provider.EntityMapper.Map(entity, dbEntity); - EntityEntry dbEntry = await UpdateCoreAsync( - entity, - dbEntity, - cancellationToken) - .ConfigureAwait(false); + EntityEntry dbEntry = await UpdateCoreAsync( + entity, + dbEntity, + cancellationToken) + .ConfigureAwait(false); - dbEntity = dbEntry.Entity; - UpdateChangeToken(dbEntry, entity); + dbEntity = dbEntry.Entity; + UpdateChangeToken(dbEntry, entity); - await Provider.SaveChangesAsync(cancellationToken) - .ConfigureAwait(false); + await Provider.SaveChangesAsync(cancellationToken) + .ConfigureAwait(false); - return Provider.EntityMapper.Map(dbEntity); - }, - (e, elapsedTimeMs) => Provider.Logger.EntityUpdated(e, elapsedTimeMs), - error => Provider.Logger.EntityUpdateFailed(error, entity)) - .ConfigureAwait(false); + return Provider.EntityMapper.Map(dbEntity); + }, + (e, elapsedTimeMs) => + { + Provider.Logger.EntityUpdated(e, elapsedTimeMs); + }, + error => + { + Provider.Logger.EntityUpdateFailed(error, entity); + }) + .ConfigureAwait(false); return result; } @@ -482,7 +522,10 @@ public virtual async Task DeleteAsync(TEntity entity, CancellationToken cancella Ensure.Arg.NotNull(entity); await DoAsync( - () => Provider.Logger.EntityDeleting(entity), + () => + { + Provider.Logger.EntityDeleting(entity); + }, async () => { var dbEntity = Provider.EntityMapper.Map(entity); @@ -495,8 +538,14 @@ await DoAsync( await Provider.SaveChangesAsync(cancellationToken) .ConfigureAwait(false); }, - elapsedTimeMs => Provider.Logger.EntityDeleted(entity, elapsedTimeMs), - error => Provider.Logger.EntityDeleteFailed(error, entity)) + elapsedTimeMs => + { + Provider.Logger.EntityDeleted(entity, elapsedTimeMs); + }, + error => + { + Provider.Logger.EntityDeleteFailed(error, entity); + }) .ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/AppCoreNet.Data.EntityFrameworkCore/Internal/DbModelProperties.cs b/src/AppCoreNet.Data.EntityFrameworkCore/Internal/DbModelProperties.cs index d62f1e4..cf945d3 100644 --- a/src/AppCoreNet.Data.EntityFrameworkCore/Internal/DbModelProperties.cs +++ b/src/AppCoreNet.Data.EntityFrameworkCore/Internal/DbModelProperties.cs @@ -8,11 +8,12 @@ using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Metadata; +// ReSharper disable once CheckNamespace namespace AppCoreNet.Data.EntityFrameworkCore; -internal class DbModelProperties +internal sealed class DbModelProperties { - private static readonly ConcurrentDictionary, DbModelProperties> _properties = new (); + private static readonly ConcurrentDictionary<(Type DbContextType, Type DbEntityType), DbModelProperties> _properties = new(); public IReadOnlyList PrimaryKeyPropertyNames { get; } @@ -22,10 +23,10 @@ internal class DbModelProperties private DbModelProperties(IModel model, Type dbEntityType) { - IEntityType? modelEntityType = model.FindEntityType(dbEntityType) !; + IEntityType? modelEntityType = model.FindEntityType(dbEntityType)!; PrimaryKeyPropertyNames = modelEntityType - .FindPrimaryKey() ! + .FindPrimaryKey()! .Properties.Select(p => p.Name) .ToList(); @@ -42,9 +43,9 @@ private DbModelProperties(IModel model, Type dbEntityType) public static DbModelProperties Get(Type dbContextType, Type dbEntityType, IModel model, Type entityType) { - return _properties.GetOrAdd((dbContextType, dbEntityType), t => + return _properties.GetOrAdd((DbContextType: dbContextType, DbEntityType: dbEntityType), t => { - var properties = new DbModelProperties(model, t.Item2); + var properties = new DbModelProperties(model, t.DbEntityType); if (typeof(IHasChangeToken).IsAssignableFrom(entityType) || typeof(IHasChangeTokenEx).IsAssignableFrom(entityType)) diff --git a/src/AppCoreNet.Data.EntityFrameworkCore/Internal/EntityModelProperties.cs b/src/AppCoreNet.Data.EntityFrameworkCore/Internal/EntityModelProperties.cs index 83dc5c9..14a7f70 100644 --- a/src/AppCoreNet.Data.EntityFrameworkCore/Internal/EntityModelProperties.cs +++ b/src/AppCoreNet.Data.EntityFrameworkCore/Internal/EntityModelProperties.cs @@ -6,9 +6,10 @@ using System.Linq; using System.Reflection; +// ReSharper disable once CheckNamespace namespace AppCoreNet.Data.EntityFrameworkCore; -internal class EntityModelProperties +internal sealed class EntityModelProperties where TEntity : class, IEntity { public Func GetIdValues { get; } diff --git a/src/AppCoreNet.Data.EntityFrameworkCore/Internal/LogEventIds.cs b/src/AppCoreNet.Data.EntityFrameworkCore/Internal/LogEventIds.cs index 049b812..f8d085e 100644 --- a/src/AppCoreNet.Data.EntityFrameworkCore/Internal/LogEventIds.cs +++ b/src/AppCoreNet.Data.EntityFrameworkCore/Internal/LogEventIds.cs @@ -3,6 +3,7 @@ using Microsoft.Extensions.Logging; +// ReSharper disable once CheckNamespace namespace AppCoreNet.Data.EntityFrameworkCore; internal static class LogEventIds diff --git a/src/AppCoreNet.Data.MongoDB/AppCoreNet.Data.MongoDB.csproj b/src/AppCoreNet.Data.MongoDB/AppCoreNet.Data.MongoDB.csproj index 2545a32..d6348ed 100644 --- a/src/AppCoreNet.Data.MongoDB/AppCoreNet.Data.MongoDB.csproj +++ b/src/AppCoreNet.Data.MongoDB/AppCoreNet.Data.MongoDB.csproj @@ -5,16 +5,9 @@ Adds Mongo DB support to AppCore .NET persistence. - - - - - - - - - + + diff --git a/src/AppCoreNet.Data.MongoDB/MongoDataProvider.cs b/src/AppCoreNet.Data.MongoDB/MongoDataProvider.cs index 223d656..09edff5 100644 --- a/src/AppCoreNet.Data.MongoDB/MongoDataProvider.cs +++ b/src/AppCoreNet.Data.MongoDB/MongoDataProvider.cs @@ -65,9 +65,8 @@ public MongoDataProvider(string name, MongoDataProviderServices services) _name = name; } - internal string GetCollectionName() - where TEntity : IEntity + internal string GetCollectionName() { - return typeof(TEntity).Name; + return typeof(TDocument).Name; } } \ No newline at end of file diff --git a/src/AppCoreNet.Data.MongoDB/MongoDataProviderOptions.cs b/src/AppCoreNet.Data.MongoDB/MongoDataProviderOptions.cs index 0e8e1b2..687e841 100644 --- a/src/AppCoreNet.Data.MongoDB/MongoDataProviderOptions.cs +++ b/src/AppCoreNet.Data.MongoDB/MongoDataProviderOptions.cs @@ -15,7 +15,7 @@ public sealed class MongoDataProviderOptions /// /// Gets or sets the used by the data provider. /// - public MongoClientSettings ClientSettings { get; set; } = new (); + public MongoClientSettings ClientSettings { get; set; } = new(); /// /// Gets or sets the name of the database. diff --git a/src/AppCoreNet.Data.MongoDB/MongoRepository.cs b/src/AppCoreNet.Data.MongoDB/MongoRepository.cs index 033e154..f106d36 100644 --- a/src/AppCoreNet.Data.MongoDB/MongoRepository.cs +++ b/src/AppCoreNet.Data.MongoDB/MongoRepository.cs @@ -138,7 +138,7 @@ public MongoRepository( Provider = provider; Collection = provider.Database.GetCollection( string.IsNullOrEmpty(collectionName) - ? provider.GetCollectionName() + ? provider.GetCollectionName() : collectionName, collectionSettings); } @@ -230,17 +230,30 @@ public async Task QueryAsync(IQuery query, C TResult result; try { - result = await DoAsync( - () => Provider.Logger.QueryExecuting(query), - async () => await queryHandler.ExecuteAsync(query, cancellationToken) - .ConfigureAwait(false), - (_, elapsedTimeMs) => Provider.Logger.QueryExecuted(query, elapsedTimeMs), - error => Provider.Logger.QueryExecuteFailed(error, query)) - .ConfigureAwait(false); + result = + await DoAsync( + () => + { + Provider.Logger.QueryExecuting(query); + }, + async () => + { + return await queryHandler.ExecuteAsync(query, cancellationToken) + .ConfigureAwait(false); + }, + (_, elapsedTimeMs) => + { + Provider.Logger.QueryExecuted(query, elapsedTimeMs); + }, + error => + { + Provider.Logger.QueryExecuteFailed(error, query); + }) + .ConfigureAwait(false); } finally { - await DisposeQueryHandler(queryHandler) + await DisposeQueryHandlerAsync(queryHandler) .ConfigureAwait(false); } @@ -252,7 +265,7 @@ await DisposeQueryHandler(queryHandler) "ReSharper", "SuspiciousTypeConversion.Global", Justification = "Handler may implement IDisposable.")] - async ValueTask DisposeQueryHandler(IMongoQueryHandler handler) + async ValueTask DisposeQueryHandlerAsync(IMongoQueryHandler handler) { switch (handler) { @@ -269,11 +282,17 @@ await disposable.DisposeAsync() return result; } + /// + /// Provides the core logic to find an entity by it's unique identifier. + /// + /// The entity identifier. + /// Optional . + /// The entity if found, otherwise null. protected virtual async Task FindCoreAsync(TId id, CancellationToken cancellationToken) { IClientSessionHandle? sessionHandle = Provider.TransactionManager.CurrentTransaction?.SessionHandle; - FilterDefinition filter = Builders.Filter.Eq("_id", id); + FilterDefinition filter = Builders.Filter.Eq(ObjectIdField, id); IFindFluent find = sessionHandle != null ? Collection.Find(sessionHandle, filter) @@ -289,31 +308,37 @@ await disposable.DisposeAsync() { Ensure.Arg.NotNull(id); - return await DoAsync( - () => Provider.Logger.EntityLoading(typeof(TEntity), id), - async () => - { - TDocument? document = await FindCoreAsync(id, cancellationToken) - .ConfigureAwait(false); - - return document != null - ? Provider.EntityMapper.Map(document) - : default; - }, - (result, elapsedTimeMs) => - { - if (result != null) + return + await DoAsync( + () => { - Provider.Logger.EntityLoaded(result, elapsedTimeMs); - } - else + Provider.Logger.EntityLoading(typeof(TEntity), id); + }, + async () => { - Provider.Logger.EntityNotFound(typeof(TEntity), id); - } - }, - error => - Provider.Logger.EntityLoadFailed(error, typeof(TEntity), id)) - .ConfigureAwait(false); + TDocument? document = await FindCoreAsync(id, cancellationToken) + .ConfigureAwait(false); + + return document != null + ? Provider.EntityMapper.Map(document) + : default; + }, + (result, elapsedTimeMs) => + { + if (result != null) + { + Provider.Logger.EntityLoaded(result, elapsedTimeMs); + } + else + { + Provider.Logger.EntityNotFound(typeof(TEntity), id); + } + }, + error => + { + Provider.Logger.EntityLoadFailed(error, typeof(TEntity), id); + }) + .ConfigureAwait(false); } /// @@ -330,6 +355,13 @@ public async Task LoadAsync(TId id, CancellationToken cancellationToken return entity; } + /// + /// Provides the core logic to update an entity. + /// + /// The entity. + /// The document. + /// Optional . + /// The updated document. protected virtual async Task UpdateCoreAsync( TEntity entity, TDocument document, @@ -387,22 +419,39 @@ public async Task UpdateAsync(TEntity entity, CancellationToken cancell $"The entity cannot be updated because the '{nameof(IEntity.Id)}' property has the default value."); } - return await DoAsync( - () => Provider.Logger.EntityUpdating(entity), - async () => - { - var document = Provider.EntityMapper.Map(entity); + return + await DoAsync( + () => + { + Provider.Logger.EntityUpdating(entity); + }, + async () => + { + var document = Provider.EntityMapper.Map(entity); - document = await UpdateCoreAsync(entity, document, cancellationToken) - .ConfigureAwait(false); + document = await UpdateCoreAsync(entity, document, cancellationToken) + .ConfigureAwait(false); - return Provider.EntityMapper.Map(document); - }, - (result, elapsedTimeMs) => Provider.Logger.EntityUpdated(result, elapsedTimeMs), - error => Provider.Logger.EntityUpdateFailed(error, entity)) - .ConfigureAwait(false); + return Provider.EntityMapper.Map(document); + }, + (result, elapsedTimeMs) => + { + Provider.Logger.EntityUpdated(result, elapsedTimeMs); + }, + error => + { + Provider.Logger.EntityUpdateFailed(error, entity); + }) + .ConfigureAwait(false); } + /// + /// Provides the core logic to create an entity. + /// + /// The entity. + /// The document. + /// Optional . + /// The created document. protected virtual async Task CreateCoreAsync( TEntity entity, TDocument document, @@ -439,22 +488,38 @@ public async Task CreateAsync(TEntity entity, CancellationToken cancell { Ensure.Arg.NotNull(entity); - return await DoAsync( - () => Provider.Logger.EntityCreating(entity), - async () => - { - var document = Provider.EntityMapper.Map(entity); + return + await DoAsync( + () => + { + Provider.Logger.EntityCreating(entity); + }, + async () => + { + var document = Provider.EntityMapper.Map(entity); - document = await CreateCoreAsync(entity, document, cancellationToken) - .ConfigureAwait(false); + document = await CreateCoreAsync(entity, document, cancellationToken) + .ConfigureAwait(false); - return Provider.EntityMapper.Map(document); - }, - (result, elapsedTimeMs) => Provider.Logger.EntityCreated(result, elapsedTimeMs), - error => Provider.Logger.EntityCreateFailed(error, entity)) - .ConfigureAwait(false); + return Provider.EntityMapper.Map(document); + }, + (result, elapsedTimeMs) => + { + Provider.Logger.EntityCreated(result, elapsedTimeMs); + }, + error => + { + Provider.Logger.EntityCreateFailed(error, entity); + }) + .ConfigureAwait(false); } + /// + /// Provides the core logic to delete an entity. + /// + /// The entity. + /// Optional . + /// The asynchronous task. protected virtual async Task DeleteCoreAsync(TEntity entity, CancellationToken cancellationToken) { IClientSessionHandle? sessionHandle = Provider.TransactionManager.CurrentTransaction?.SessionHandle; @@ -491,14 +556,23 @@ public async Task DeleteAsync(TEntity entity, CancellationToken cancellationToke Ensure.Arg.NotNull(entity); await DoAsync( - () => Provider.Logger.EntityDeleting(entity), + () => + { + Provider.Logger.EntityDeleting(entity); + }, async () => { await DeleteCoreAsync(entity, cancellationToken) .ConfigureAwait(false); }, - elapsedTimeMs => Provider.Logger.EntityDeleted(entity, elapsedTimeMs), - error => Provider.Logger.EntityDeleteFailed(error, entity)) + elapsedTimeMs => + { + Provider.Logger.EntityDeleted(entity, elapsedTimeMs); + }, + error => + { + Provider.Logger.EntityDeleteFailed(error, entity); + }) .ConfigureAwait(false); } } \ No newline at end of file diff --git a/src/AppCoreNet.Data.MongoDB/MongoTransactionManager.cs b/src/AppCoreNet.Data.MongoDB/MongoTransactionManager.cs index e8ced82..de90762 100644 --- a/src/AppCoreNet.Data.MongoDB/MongoTransactionManager.cs +++ b/src/AppCoreNet.Data.MongoDB/MongoTransactionManager.cs @@ -24,7 +24,7 @@ namespace AppCoreNet.Data.MongoDB; public sealed class MongoTransactionManager : ITransactionManager { private readonly IMongoClient _client; - private readonly AsyncLocal _currentTransaction = new (); + private readonly AsyncLocal _currentTransaction = new(); private readonly DataProviderLogger _logger; /// diff --git a/src/AppCoreNet.Data/AppCoreNet.Data.csproj b/src/AppCoreNet.Data/AppCoreNet.Data.csproj index a64f870..b43dc6b 100644 --- a/src/AppCoreNet.Data/AppCoreNet.Data.csproj +++ b/src/AppCoreNet.Data/AppCoreNet.Data.csproj @@ -6,15 +6,8 @@ - - - - - - - - - + + diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 3efd5ba..8e5ec29 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -6,13 +6,13 @@ - + all - + all - + all diff --git a/test/AppCoreNet.Data.EntityFrameworkCore.Tests/AppCoreNet.Data.EntityFrameworkCore.Tests.csproj b/test/AppCoreNet.Data.EntityFrameworkCore.Tests/AppCoreNet.Data.EntityFrameworkCore.Tests.csproj index e1d6b7d..8a2e11c 100644 --- a/test/AppCoreNet.Data.EntityFrameworkCore.Tests/AppCoreNet.Data.EntityFrameworkCore.Tests.csproj +++ b/test/AppCoreNet.Data.EntityFrameworkCore.Tests/AppCoreNet.Data.EntityFrameworkCore.Tests.csproj @@ -1,21 +1,12 @@ - net8.0;net6.0 - $(TargetFrameworks);net462 + net9.0;net8.0 AppCoreNet.Data.EntityFrameworkCore - - - - - - - - - - + + diff --git a/test/AppCoreNet.Data.MongoDB.Tests/AppCoreNet.Data.MongoDB.Tests.csproj b/test/AppCoreNet.Data.MongoDB.Tests/AppCoreNet.Data.MongoDB.Tests.csproj index 992e766..d8b0b1e 100644 --- a/test/AppCoreNet.Data.MongoDB.Tests/AppCoreNet.Data.MongoDB.Tests.csproj +++ b/test/AppCoreNet.Data.MongoDB.Tests/AppCoreNet.Data.MongoDB.Tests.csproj @@ -1,8 +1,8 @@  - net8.0;net6.0 - $(TargetFrameworks);net462 + net9.0;net8.0 + $(TargetFrameworks);net472 AppCoreNet.Data.MongoDB @@ -12,7 +12,7 @@ - + diff --git a/test/AppCoreNet.Data.MongoDB.Tests/DAO/TestEntity2.cs b/test/AppCoreNet.Data.MongoDB.Tests/DAO/TestEntity2.cs index 219be31..a2cb81c 100644 --- a/test/AppCoreNet.Data.MongoDB.Tests/DAO/TestEntity2.cs +++ b/test/AppCoreNet.Data.MongoDB.Tests/DAO/TestEntity2.cs @@ -9,7 +9,7 @@ namespace AppCoreNet.Data.MongoDB.DAO; public class TestEntity2 { [BsonId] - public ComplexId Id { get; set; } = new () { Id = Guid.Empty, Version = 0 }; + public ComplexId Id { get; set; } = new() { Id = Guid.Empty, Version = 0 }; public string? Name { get; set; } diff --git a/test/AppCoreNet.Data.MongoDB.Tests/MongoRepositoryTests.cs b/test/AppCoreNet.Data.MongoDB.Tests/MongoRepositoryTests.cs index 65e10e8..be18efb 100644 --- a/test/AppCoreNet.Data.MongoDB.Tests/MongoRepositoryTests.cs +++ b/test/AppCoreNet.Data.MongoDB.Tests/MongoRepositoryTests.cs @@ -55,7 +55,7 @@ protected override void ConfigureServices(IServiceCollection services) var mongo = (MongoDataProvider)provider; TDao document = - await mongo.Database.GetCollection(mongo.GetCollectionName()) + await mongo.Database.GetCollection(mongo.GetCollectionName()) .Find(expression) .FirstOrDefaultAsync(); @@ -111,7 +111,7 @@ protected override async Task CreateDataEntity(IDataProvider provider, E var mongo = (MongoDataProvider)provider; IMongoCollection collection = - mongo.Database.GetCollection(mongo.GetCollectionName()); + mongo.Database.GetCollection(mongo.GetCollectionName()); var dataEntity = Mapper.Map(entity); await collection.InsertOneAsync(dataEntity); @@ -123,7 +123,7 @@ protected override async Task CreateDataEntity(IDataProvider provider, E var mongo = (MongoDataProvider)provider; IMongoCollection collection = - mongo.Database.GetCollection(mongo.GetCollectionName()); + mongo.Database.GetCollection(mongo.GetCollectionName()); var dataEntity = Mapper.Map(entity); await collection.InsertOneAsync(dataEntity); diff --git a/test/AppCoreNet.Data.MongoDB.Tests/MongoFixture.cs b/test/AppCoreNet.Data.MongoDB.Tests/MongoTestFixture.cs similarity index 100% rename from test/AppCoreNet.Data.MongoDB.Tests/MongoFixture.cs rename to test/AppCoreNet.Data.MongoDB.Tests/MongoTestFixture.cs diff --git a/test/AppCoreNet.Data.SpecificationTests/AppCoreNet.Data.SpecificationTests.csproj b/test/AppCoreNet.Data.SpecificationTests/AppCoreNet.Data.SpecificationTests.csproj index 03070be..05ce8d9 100644 --- a/test/AppCoreNet.Data.SpecificationTests/AppCoreNet.Data.SpecificationTests.csproj +++ b/test/AppCoreNet.Data.SpecificationTests/AppCoreNet.Data.SpecificationTests.csproj @@ -1,8 +1,8 @@  - net8.0;net6.0 - $(TargetFrameworks);net462 + net9.0;net8.0 + $(TargetFrameworks);net472 false AppCoreNet.Data @@ -11,19 +11,9 @@ - - - - - - - - - - - - - + + + diff --git a/test/AppCoreNet.Data.SpecificationTests/Entities/TestEntity2.cs b/test/AppCoreNet.Data.SpecificationTests/Entities/TestEntity2.cs index 8902bc9..a53f299 100644 --- a/test/AppCoreNet.Data.SpecificationTests/Entities/TestEntity2.cs +++ b/test/AppCoreNet.Data.SpecificationTests/Entities/TestEntity2.cs @@ -7,7 +7,7 @@ namespace AppCoreNet.Data.Entities; public class TestEntity2 : IEntity, IHasChangeTokenEx { - public ComplexId Id { get; set; } = new () { Id = Guid.Empty, Version = 0 }; + public ComplexId Id { get; set; } = new() { Id = Guid.Empty, Version = 0 }; object IEntity.Id => Id; diff --git a/test/AppCoreNet.Data.Tests/AppCoreNet.Data.Tests.csproj b/test/AppCoreNet.Data.Tests/AppCoreNet.Data.Tests.csproj index 003a799..edca0be 100644 --- a/test/AppCoreNet.Data.Tests/AppCoreNet.Data.Tests.csproj +++ b/test/AppCoreNet.Data.Tests/AppCoreNet.Data.Tests.csproj @@ -1,21 +1,13 @@ - net8.0;net6.0 - $(TargetFrameworks);net462 + net9.0;net8.0 + $(TargetFrameworks);net472 AppCoreNet.Data - - - - - - - - - - + + diff --git a/test/Directory.Build.props b/test/Directory.Build.props index 27a8cd8..6e1c272 100644 --- a/test/Directory.Build.props +++ b/test/Directory.Build.props @@ -7,23 +7,23 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all