[英]Audit.NET connected object save issue
我將 Audit.NET 與 EntityFramework 擴展一起使用,當我僅跟蹤 1 個實體時,一切運行良好。
現在我也在跟蹤連接到第一個實體的另一個實體,當我嘗試保存它時,審計保存函數會拋出一個反射錯誤
System.Reflection.TargetException: '對象與目標類型不匹配。'
我的類的結構是這樣的:
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
}
然后我只是將我的審計類建模為完全相同但添加了審計字段
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
}
然后在 FirstClassAudit 中省略了對 SecondClass 的引用
我的兩個類都在 DbContext 中,審計類每個都映射到一個單獨的表。 我在 AuditTypeExplicitMapper 下添加了這兩個類的映射,我調試通過沒有問題。 但是我仍然在 SaveChanges 函數上遇到錯誤
當我保存時將 SecondClass 引用保留為 null 時,這似乎不會發生
編輯:更多信息
審計.NET 配置:
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 中保存函數:
public override int SaveChanges()
{
return Helper.SaveChanges(auditContext, () => base.SaveChanges());
}
編輯 2:堆棧跟蹤
在 System.Reflection.RuntimeMethodInfo.CheckConsistency(Object target) 在 System.Reflection.RuntimeMethodInfo.InvokeArgumentsCheck(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) 在 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 definitionType, 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范圍,EntityFrameworkEvent 事件)在 Audit.EntityFramework.DbContextHelper.SaveChanges(IAuditDbContext context, Func`1 baseSaveChanges) 在 MyDbContex t.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) [MyLocalPath]\\FirstClassManager.cs:第 244 行在 FirstClassController.<>c__DisplayClass20_0.b__0() 在 [MyLocalPath]\\FirstClassController.cs:第 249 行
編輯:在稍微擺弄之后,我得到了錯誤,通過將“MySpecialClass”添加到映射中來說明它是什么類型
System.ArgumentException: 'MySpecialClass' 類型的對象無法轉換為'AuditMySpecialClass' 類型。
這個類是我的數據上下文中的一個擁有類型,這可能與它有關,也可能不是。
現在錯誤似乎在它到達您可以添加到映射中的用戶定義的操作之前被拋出,可能 Audit.NET 試圖在用戶定義的操作之前映射這些東西?
使用最新版本的Audit.EntityFramework (15.0.2),您現在可以僅忽略某些審計類型的屬性匹配,如下所示:
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
);
所以,我找到了一個解決方案。 這不是我想要的 100%,但它有效。
問題出在我的“MySpecialClass”對象上,因為它們是 EFCore 擁有的類型,它們生成了自己的單獨事件,這讓 Audit.NET 感到困惑
因此,我在“MySpecialClass”聲明上方添加了 [AuditIgnore] 並將 IgnoreMatchedProperties 添加到配置中
[AuditIgnore]
public class MySpecialClass
{
public Unit? UnitOfMeasure { get; set; }
public float? Value { get; set; }
}
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”有特殊例外
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);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.