我一直试图通过TrackChanges创建审计跟踪尝试许多不同的方法,覆盖SaveChanges()
并简单地抓取实体并使用DbEntityEntry.OriginalValues
获取原始值这些方法最终归结为同样的问题。当我将另一个模型引用为ICollection
时,它不会在实体中记录此模型。
作为此问题的基本解释,请参阅以下代码:
public void Update(Project project)
{
_ctx.OriginalValues(project);
_ctx.Projects.Attach(project);
_ctx.Entry(project).State = EntityState.Modified;
_ctx.SaveChanges(project);
}
上面的.OriginalValues
在引发保存更改之前将实体传递给此方法,并且我能够在用户更改之前读取实体中的值。 OriginalValues
方法如下所示:
public void OriginalValues(object entity)
{
var entry = this.Entry(entity);
System.Reflection.PropertyInfo[] names = entity.GetType().GetProperties();
foreach (var property in names)
{
var n = entry.OriginalValues[property.Name];
}
}
我所理解的上述方法并不是非常优雅或最佳实践,但这是尝试从我的实体中读取原始值的最新尝试。
当此代码运行时,property.Name
将会出现一个名为“团队”的名称。在项目模型中引用它:
public class Project
{
public int Id { get; set; } // PK
public string Name { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int MarketId { get; set; } // FK
[ForeignKey("MarketId")]
public Market Market { get; set; } // FK Nav
public ICollection<Team> Teams { get; set; } // Many to Many Nav
}
抛出一个错误,告诉我它还没有映射到Project,即使我已经使用了流畅的API和数据注释来尝试获取此映射。
这是一个例子,我在其他模型中遇到相同的情况,但有许多关系。
我是一名研究生开发人员,因此没有大量的.net信息我希望有人可以提供任何建议或支持,如果可能的话!
由于
编辑:显示错误消息:
&#39;团队&#39;属性不存在或未映射类型&#39;项目&#39;。
描述:执行当前Web请求期间发生了未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。
异常详细信息:System.ArgumentException:&#39; Teams&#39;属性不存在或未映射类型&#39;项目&#39;。
来源错误:
Line 78: foreach (var property in names)
Line 79: {
Line 80: var n = entry.OriginalValues[property.Name];
Line 81:
Line 82: }
答案 0 :(得分:3)
出现此错误是因为EF将每个条目的值保存在其自己的对象中,因此导航属性的值将保存在其条目中,因此它们不在当前对象的OriginalValues
中。您可以访问导航属性,如下所示:
foreach (var property in names)
{
var m = entry.Member(property.Name);
if (m is DbPropertyEntry)//simple property
{
var p = entry.Property(property.Name);
}
if (m is DbReferenceEntry)//navigation to single object
{
var r = entry.Reference(property.Name);
}
if (m is DbCollectionEntry)//navigation to collection
{
var c = entry.Collection(property.Name);
}
}
然后,您可以将每个导航对象视为新对象并检索它们的原始值。
<强>建议:强> EF内部有一个跟踪系统,可跟踪对象图的所有更改,您可以查询此跟踪系统并记录更改,如下所示。无需跟踪引用,因为如果它们发生了更改,则EF会检测它。
public void OriginalValues(object entity)
{
ChangeTracker.DetectChanges();
var changed = ChangeTracker.Entries()
.Where(x=>x.State != EntityState.Unchanged).ToList();
foreach (var entry in changed)
{
switch (entry.State)
{
case EntityState.Added:
Debug.WriteLine("object of type " + entry.Entity.GetType().Name
+ "created:");
foreach(var name in entry.CurrentValues.PropertyNames)
{
Debug.WriteLine(name + " : " + entry.CurrentValues[name]);
}
break;
case EntityState.Deleted:
Debug.WriteLine("object of type " + entry.Entity.GetType().Name
+ "deleted:");
foreach(var name in entry.OriginalValues.PropertyNames)
{
Debug.WriteLine(name + " : " + entry.OriginalValues[name]);
}
break;
case EntityState.Modified:
Debug.WriteLine("object of type " + entry.Entity.GetType().Name
+ "updated:");
Debug.WriteLine("current values:");
foreach(var name in entry.CurrentValues.PropertyNames)
{
Debug.WriteLine(name + " : " + entry.CurrentValues[name]);
}
Debug.WriteLine("original values:");
foreach(var name in entry.OriginalValues.PropertyNames)
{
Debug.WriteLine(name + " : " + entry.OriginalValues[name]);
}
break;
}
}
}
注意:确保在删除对象时将状态设置为Deleted
。