I'm using Audit.NET with the EntityFramework extension, and everything was running fine when I was tracking just 1 entity.
Now I'm tracking another entity as well that is connected to that first entity, and when I try to save it, the audit save function throws a Reflection error
System.Reflection.TargetException: 'Object does not match target type.'
The structure of my classes is like so:
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
}
Then I just modeled my Audit classes to be the exact same but with added audit fields
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
}
And then left out the reference to SecondClass in FirstClassAudit
Both of my classes are in the DbContext, the audit classes are each mapped to a separate table. I added the mappings for both classes under an AuditTypeExplicitMapper, which I debugged through without issue. And yet I still get an error on the SaveChanges function
This does not seem to happen when I leave the SecondClass reference as null when I save
EDIT: Some more information
Audit.NET config:
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;
}))
);
Save function in DbContext:
public override int SaveChanges()
{
return Helper.SaveChanges(auditContext, () => base.SaveChanges());
}
EDIT 2: Stack trace
at System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target) at System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) at System.Reflection.RuntimePropertyInfo.GetValue(Object obj, Object[] index) at Audit.EntityFramework.Providers.EntityFrameworkDataProvider.CreateAuditEntity(Type definingType, Type auditType, EventEntry entry) at Audit.EntityFramework.Providers.EntityFrameworkDataProvider.InsertEvent(AuditEvent auditEvent) at Audit.Core.AuditScope.SaveEvent(Boolean forceInsert) at Audit.Core.AuditScope.Save() at Audit.EntityFramework.DbContextHelper.SaveScope(IAuditDbContext context, AuditScope scope, EntityFrameworkEvent event) at Audit.EntityFramework.DbContextHelper.SaveChanges(IAuditDbContext context, Func`1 baseSaveChanges) at MyDbContext.SaveChanges() in [MyLocalPath]\MyDbContext.cs:line 132 at FirstClassRepository.UpdateFirstClass(Int32 id, FirstClassDto first) in [MyLocalPath]\FirstClassRepository.cs:line 209 at FirstClassManager.UpdateFirstClass(Int32 id, FirstClassDto dto) in [MyLocalPath]\FirstClassManager.cs:line 244 at FirstClassController.<>c__DisplayClass20_0.b__0() in [MyLocalPath]\FirstClassController.cs:line 249
EDIT: After fiddling around a bit more I got the error to say what type it was by adding 'MySpecialClass' to the mappings
System.ArgumentException: 'Object of type 'MySpecialClass' cannot be converted to type 'AuditMySpecialClass'.'
This class is an Owned Type within my datacontext, this may have something to do with it, maybe not.
Right now the error seems to get thrown before it gets to the user defined action that you can add in the mapping, possibly Audit.NET is trying to map these things before the user defined action?