【问题标题】:Storing a property value into another table将属性值存储到另一个表中
【发布时间】:2018-09-28 05:27:25
【问题描述】:

我正在寻找一种将类的某些属性的值复制到数据库中的另一个表的方法。有没有什么特殊的方法可以将一个类的属性标记为需要将它们的值存储在 2 个位置(一个作为其自己的域对象的一部分,另一个作为另一个域对象的一部分,比如摘要)?

我有一个被审计的实体如下:

public class Audited 
{
    public virtual int Id{ get; set; }

    public virtual string FieldName{ get; set; }

    public virtual string FieldValue{ get; set; }
}

以及其他实体,例如:

public class Plan : FullAuditedEntity
{
    [ToBeAudited]
    public virtual int PlanName{ get; set; }

    public DateTime Date { get; set; }
}

我正在寻找一种能够使用属性(例如 [ToBeAudited])标记类属性的方法,以便在插入或更新时将属性值复制到审核表中

我已将 [已审核] (Abp.Auditing) 添加到 PlanName 并在日志中收到以下错误:

错误 2018-04-20 10:02:09,286 [5] Mvc.ExceptionHandling.AbpExceptionFilter - 对象引用未设置为对象的实例。 System.NullReferenceException:对象引用未设置为对象的实例。 在 Abp.EntityHistory.EntityHistoryHelper.ShouldSavePropertyHistory(PropertyEntry propertyEntry, Boolean defaultValue) 在 Abp.EntityHistory.EntityHistoryHelper.GetPropertyChanges(EntityEntry entityEntry) 在 Abp.EntityHistory.EntityHistoryHelper.CreateEntityChangeInfo(EntityEntry entityEntry) 在 Abp.EntityHistory.EntityHistoryHelper.CreateEntityChangeSet(ICollection1 entityEntries) at Abp.Zero.EntityFrameworkCore.AbpZeroCommonDbContext3.d__98.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.d__20.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.d__12.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Abp.EntityFrameworkCore.Uow.EfCoreUnitOfWork.d__14.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Abp.Domain.Uow.UnitOfWorkBase.d__57.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Abp.AspNetCore.Mvc.Uow.AbpUowActionFilter.d__4.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__10.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext 上下文) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(状态&下一个,范围&范围,对象&状态,布尔& isCompleted) 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__14.MoveNext() --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务) 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.d__23.MoveNext()

【问题讨论】:

    标签: c# aspnetboilerplate


    【解决方案1】:

    您可以利用 ABP 的 Entity History 功能(无需此自定义即可使用)。

    此答案假定AuditedEntity 以便轻松使用IRepository,但不一定是:

    public class Audited : Entity
    {
        public virtual int EntityId { get; set; }
    
        public virtual string FieldName { get; set; }
    
        public virtual string FieldValue { get; set; }
    }
    

    首先,实现IEntityHistoryStore

    public class MyEntityHistoryStore : IEntityHistoryStore
    {
        private readonly IRepository<Audited> _auditedRepository;
    
        public MyEntityHistoryStore(IRepository<Audited> auditedRepository)
        {
            _auditedRepository = auditedRepository;
        }
    
        public async Task SaveAsync(EntityChangeSet entityChangeSet)
        {
            foreach (var entityChange in entityChangeSet.EntityChanges)
            {
                var entityType = entityChange.EntityEntry.As<EntityEntry>().Entity.GetType();
    
                foreach (var propertyChange in entityChange.PropertyChanges)
                {
                    var property = entityType.GetProperty(propertyChange.PropertyName);
                    if (property.IsDefined(typeof(ToBeAuditedAttribute)))
                    {
                        await _auditedRepository.InsertAsync(new Audited
                        {
                            EntityId = JsonConvert.DeserializeObject<int>(entityChange.EntityId),
                            FieldName = propertyChange.PropertyName,
                            FieldValue = propertyChange.NewValue
                        });
                    }
                }
            }
        }
    }
    

    接下来,替换服务并添加到模块的PreInitialize 方法中的Selectors

    // using Abp.Configuration.Startup;
    
    Configuration.ReplaceService<IEntityHistoryStore, MyEntityHistoryStore>();
    Configuration.EntityHistory.Selectors.Add(
        new NamedTypeSelector(
            "ToBeAuditedEntities",
            type => type.GetProperties().Any(p => p.IsDefined(typeof(ToBeAuditedAttribute)))
        )
    );
    

    那么,照常Insert

    _planRepository.Insert(new Plan
    {
        PlanName = 42
    });
    

    Audited表:

    【讨论】:

    • 我还没有完成您的更改,只是根据文档将 [已审核] 属性添加到我的一个实体中,并且我正在获取 System.NullReferenceException:Object reference not set to an object of an instance。在 Abp.EntityHistory.EntityHistoryHelper.ShouldSavePropertyHistory(PropertyEntry propertyEntry, Boolean defaultValue) 在 Abp.EntityHistory.EntityHistoryHelper.GetPropertyChanges(EntityEntry entityEntry) 在 Abp.EntityHistory.EntityHistoryHelper.CreateEntityChangeInfo(EntityEntry entityEntry) 在 Abp.EntityHistory.EntityHistoryHelper.CreateEntityChangeSet(ICollection` 1 个实体条目)
    • 在 ABP v3.6 中修复。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-16
    • 2019-10-13
    • 2012-07-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多