首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Audit.NET连接对象保存问题

Audit.NET连接对象保存问题
EN

Stack Overflow用户
提问于 2020-01-15 13:30:25
回答 2查看 615关注 0票数 4

我使用的是带有Audit.NET扩展的EntityFramework,当我只跟踪一个实体时,一切都很好。

现在我也在跟踪另一个连接到第一个实体的实体,当我试图保存它时,审计保存函数抛出一个反射错误

System.Reflection.TargetException:“Object与目标类型不匹配。”

我的班级结构是这样的:

代码语言:javascript
复制
public class FirstClass{
  public int ID{get;set;}
  //Some props here
  public SecondClass SecondClass{get;set}
}

public class SecondClass{
  public int ID{get;set;}
  public int FirstClassId{get;set;}
  public MySpecialClass JustForData{get;set;}
  //Some other props here
}

然后,我只是将我的审计类建模为完全相同,但添加了审计字段

代码语言:javascript
复制
public class AuditClass{
  public Guid AuditId{get;set;}
  public string AuditMessage{get;set;}
}

public class FirstClassAudit : AuditClass{
  public int ID{get;set;}
  //Some props here
  //No SecondClass prop here
}

public class SecondClassAudit: AuditClass{
  public int ID{get;set;}
  public int FirstClassId{get;set;}
  public MySpecialClass JustForData{get;set;}
  //Some other props here
}

然后省略对SecondClass在FirstClassAudit中的引用。

我的两个类都在DbContext中,每个审计类都映射到一个单独的表中。我在AuditTypeExplicitMapper下为两个类添加了映射,我在没有问题的情况下调试了这两个类。但是在SaveChanges函数上仍然有一个错误

当我将SecondClass引用保留为null时,这种情况似乎不会发生。

编辑:更多信息

Audit.NET配置:

代码语言:javascript
复制
Audit.Core.Configuration.Setup()
                .UseEntityFramework(
                ef => ef
                    .AuditTypeExplicitMapper(m => m
                    .Map<FirstClass, FirstClassAudit>((frst, auditFrst) =>
                    {
                        //Map the tag fields in here
                        auditFrst.Tag = frst.Installation.Tag;
                        //Some more props here
                    })
                    .Map<SecondClass, SecondClassAudit>()
                    .AuditEntityAction((ev, ent, auditEntity) =>
                    {
                        ((AuditClass)auditEntity).AuditMessage = ent.Action;
                    }))
                );

在DbContext中保存函数:

代码语言:javascript
复制
public override int SaveChanges()
        {
            return Helper.SaveChanges(auditContext, () => base.SaveChanges());
        }

编辑2:堆栈跟踪

(在System.Reflection.RuntimeMethodInfo.CheckConsistency(Object目标)在System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj,BindingFlags invokeAttr,binder粘合剂,Object[]参数,CultureInfo培养)在System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,binder粘合剂,Object[]参数,CultureInfo培养)在System.Reflection.RuntimePropertyInfo.GetValue(Object obj,Object[]索引)在Audit.EntityFramework.Providers.EntityFrameworkDataProvider.CreateAuditEntity(Type definingType,auditType类型,( Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(AuditEvent auditEvent)在Audit.Core.AuditScope.SaveEvent(布尔forceInsert) at Audit.Core.AuditScope.Save() at Audit.Core.AuditScope.Save(),AuditScope范围,EntityFrameworkEvent事件在Audit.EntityFramework.DbContextHelper.SaveChanges(IAuditDbContext上下文中,Func`1‘1 baseSaveChanges( MyDbContext.SaveChanges() at MyDbContext.SaveChanges() at FirstClassRepository.UpdateFirstClass(Int32 id,Int32 id,( FirstClassController.<>c__DisplayClass20_0.b__0() at FirstClassManager.UpdateFirstClass(Int32 id,FirstClassDto dto) MyLocalPath\FirstClassManager.cs:line 244 at MyLocalPath\FirstClassController.cs:line 249

编辑:在修改了更多之后,通过在映射中添加“MySpecialClass”,我得到了一个错误,可以说明它是哪种类型

System.ArgumentException:'MySpecialClass‘类型的对象不能转换为’AuditMySpecialClass‘类型。“

这个类是我的数据文本中的一个拥有类型,这可能与它有关,也许不是。

现在,错误似乎在您可以添加到映射中的用户定义操作之前抛出,可能是Audit.NET试图在用户定义的操作之前映射这些操作吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-20 11:26:06

所以我找到了解决办法。这不是我想要的100%,但它是有效的。

问题是,当我的"MySpecialClass“对象与EFCore一起拥有类型时,它们生成了自己的独立事件,这使Audit.NET感到困惑。

因此,我在"MySpecialClass“声明的前面添加了IgnoreMatchedProperties,并将IgnoreMatchedProperties添加到配置中。

代码语言:javascript
复制
[AuditIgnore]
public class MySpecialClass
{
  public Unit? UnitOfMeasure { get; set; }

  public float? Value { get; set; }
}
代码语言:javascript
复制
Audit.Core.Configuration.Setup()
                .UseEntityFramework(
                ef => ef
                    .AuditTypeExplicitMapper(m => m
                    .Map<FirstClass, FirstClassAudit>((frst, auditFrst) =>
                    {
                        MapMatchedProperties(frst, auditFrst);
                        //Map the tag fields in here
                        auditFrst.Tag = frst.Installation.Tag;
                        //Some more props here
                    })
                    .Map<SecondClass, SecondClassAudit>((scnd, auditScnd)=>
                    {
                        MapMatchedProperties(scnd, auditScnd);
                    })
                    .AuditEntityAction((ev, ent, auditEntity) =>
                    {
                        ((AuditClass)auditEntity).AuditMessage = ent.Action;
                    }))
                    .IgnoreMatchedProperties()
                );

此外,我还添加了自己的映射函数"MapMatchedProperties“,以正确映射每个字段,但"MySpecialClass”有特殊例外。

代码语言:javascript
复制
private static void MapMatchedProperties(object source, object destination)
        {
            var sourceType = source.GetType();
            var destinationType = destination.GetType();

            var sourceFields = sourceType.GetProperties();
            var destinationFields = destinationType.GetProperties();

            foreach (var field in sourceFields)
            {
                var destinationField = destinationFields.FirstOrDefault(f => f.Name.Equals(field.Name));

                if (destinationField != null && (destinationField.PropertyType == field.PropertyType))
                {
                    //Normal field
                    var sourceValue = field.GetValue(source);

                    destinationField.SetValue(destination, sourceValue);
                } else if(destinationField != null && (destinationField.PropertyType == typeof(AuditMySpecialClass) && field.PropertyType== typeof(MySpecialClass)))
                {
                    //MySpecialClass field
                    var destinationMeasure = new AuditMySpecialClass();

                    var sourceValue = (MySpecialClass)field.GetValue(source);

                    if (sourceValue != null || sourceValue.IsEmpty())
                    {
                        destinationMeasure.UnitOfMeasure = sourceValue.UnitOfMeasure;
                        destinationMeasure.Value = sourceValue.Value;
                    }

                    destinationField.SetValue(destination, destinationMeasure);
                }
            }
        }
票数 0
EN

Stack Overflow用户

发布于 2020-01-20 20:34:55

使用最新版本的Audit.EntityFramework (15.0.2),您现在可以忽略某些审计类型的属性匹配,如下所示:

代码语言:javascript
复制
Audit.Core.Configuration.Setup()
    .UseEntityFramework(ef => ef
        .AuditTypeExplicitMapper(m => m
          .Map<FirstClass, FirstClassAudit>((frst, auditFrst) =>
          {
            auditFrst.Tag = frst.Installation.Tag;
          })
          .Map<SecondClass, SecondClassAudit>()
          .AuditEntityAction((ev, ent, auditEntity) =>
          {
            ((AuditClass)auditEntity).AuditMessage = ent.Action;
          }))
        .IgnoreMatchedProperties(t => t == typeof(FirstClassAudit)) // <-- Ignore prop. matching for FirstClassAudit
    );
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59752454

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档