EntityFrameworkCore.AuditTrail icon indicating copy to clipboard operation
EntityFrameworkCore.AuditTrail copied to clipboard

It doesn't work with .NET 6

Open NayLinHtke opened this issue 3 years ago • 3 comments

"System.MissingMethodException: Method not found: 'System.String Microsoft.EntityFrameworkCore.Metadata.IPropertyBase.get_Name()'. at AspNetCoreHero.EntityFrameworkCore.AuditTrail.AuditableContext.OnBeforeSaveChanges(String userId) at AspNetCoreHero.EntityFrameworkCore.AuditTrail.AuditableContext.SaveChangesAsync(String userId) at StoreManager.Infrastructure.DbContexts.ApplicationDbContext.SaveChangesAsync(CancellationToken cancellationToken) in D:\All_Web\Research\StoreManager\StoreManager\StoreManager.Infrastructure\DbContexts\ApplicationDbContext.cs:line 54 at StoreManager.Infrastructure.Repositories.UnitOfWork.Commit(CancellationToken cancellationToken) in D:\All_Web\Research\StoreManager\StoreManager\StoreManager.Infrastructure\Repositories\UnitOfWork.cs:line 24 at StoreManager.Application.Features.Brands.Commands.Create.CreateBrandCommandHandler.Handle(CreateBrandCommand request, CancellationToken cancellationToken) in D:\All_Web\Research\StoreManager\StoreManager\StoreManager.Application\Features\Brands\Commands\Create\CreateBrandCommand.cs:line 36 at MediatR.Pipeline.RequestExceptionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next) at MediatR.Pipeline.RequestExceptionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next) at MediatR.Pipeline.RequestExceptionActionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next) at MediatR.Pipeline.RequestExceptionActionProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next) at MediatR.Pipeline.RequestPostProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next) at MediatR.Pipeline.RequestPreProcessorBehavior2.Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate1 next) at StoreManager.Web.Areas.Catalog.Controllers.BrandController.OnPostCreateOrEdit(Int32 id, BrandViewModel brand) in D:\All_Web\Research\StoreManager\StoreManager\StoreManager.Web\Areas\Catalog\Controllers\BrandController.cs:line 63 at lambda_method492(Closure , Object ) at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Localization.RequestLocalizationMiddleware.Invoke(HttpContext context) at AspNetCoreHero.ToastNotification.Middlewares.NotyfMiddleware.InvokeAsync(HttpContext context, RequestDelegate next) at Microsoft.AspNetCore.Builder.UseMiddlewareExtensions.<>c__DisplayClass6_1.<<UseMiddlewareInterface>b__1>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

NayLinHtke avatar Jan 03 '22 03:01 NayLinHtke

Facing Same problem

learnwithkawsar avatar Jul 23 '22 16:07 learnwithkawsar

same here

RayBuildN22 avatar Aug 06 '22 18:08 RayBuildN22

For me this code worked in .net 6, I only had to update the OnBeforeSaveChanges method.

In the updated code, entry.Metadata.GetTableName() is used to get the table name instead of entry.Entity.GetType().Name. Also, entry.State and entry.Properties are accessed through ChangeTracker.Entries() and property.Metadata is used instead of property.

private List<AuditEntry> OnBeforeSaveChanges(string userId)
{
    ChangeTracker.DetectChanges();
    var auditEntries = new List<AuditEntry>();
    foreach (var entry in ChangeTracker.Entries())
    {
        if (entry.Entity is Audit || entry.State == EntityState.Detached || entry.State == EntityState.Unchanged)
            continue;

        var auditEntry = new AuditEntry(entry);
        auditEntry.TableName = entry.Metadata.GetTableName();
        auditEntry.UserId = userId;
        auditEntries.Add(auditEntry);
        foreach (var property in entry.Properties)
        {
            if (property.IsTemporary)
            {
                auditEntry.TemporaryProperties.Add(property);
                continue;
            }

            string propertyName = property.Metadata.Name;
            if (property.Metadata.IsPrimaryKey())
            {
                auditEntry.KeyValues[propertyName] = property.CurrentValue;
                continue;
            }

            switch (entry.State)
            {
                case EntityState.Added:
                    auditEntry.AuditType = Enums.AuditType.Create;
                    auditEntry.NewValues[propertyName] = property.CurrentValue;
                    break;

                case EntityState.Deleted:
                    auditEntry.AuditType = Enums.AuditType.Delete;
                    auditEntry.OldValues[propertyName] = property.OriginalValue;
                    break;

                case EntityState.Modified:
                    if (property.IsModified)
                    {
                        auditEntry.ChangedColumns.Add(propertyName);
                        auditEntry.AuditType = Enums.AuditType.Update;
                        auditEntry.OldValues[propertyName] = property.OriginalValue;
                        auditEntry.NewValues[propertyName] = property.CurrentValue;
                    }
                    break;
            }
        }
    }
    foreach (var auditEntry in auditEntries.Where(_ => !_.HasTemporaryProperties))
    {
        AuditLogs.Add(auditEntry.ToAudit());
    }
    return auditEntries.Where(_ => _.HasTemporaryProperties).ToList();
}

guisantos avatar May 02 '23 17:05 guisantos