DMC*_*DMC 9 .net change-tracking ef-code-first entity-framework-4.1
我有一个我继承的基类,它与其他实体有两个零到多的关系:
public abstract class WebObject
{
public WebObject()
{
RelatedTags = new List<Tag>();
RelatedWebObjects = new List<WebObject>();
}
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public Guid Id { get; set; }
public string MetaKeywords { get; set; }
public string MetaDescription { get; set; }
[InverseProperty("WebObjects")]
public virtual WebSite WebSite { get; set; }
[Required(ErrorMessage = "Every WebObject must be associated with a WebSite.")]
public Guid WebSiteId { get; set; }
public virtual ICollection<Tag> RelatedTags { get; set; }
public IList<Guid> RelatedTagIds { get; set; }
public virtual ICollection<WebObject> RelatedWebObjects { get; set; }
public IList<Guid> RelatedWebObjectIds { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在SaveChanges期间使用ChangeTracker查看实体时,我很难获得这些关系的原始值(RelatedWebObjects和RelatedTags).我可以看到之前和之后的所有标量值,我可以看到新的关系,但我看不到旧的关系.我尝试过使用Member和Collection方法,但那些只显示当前值; 不是旧的.另外我不喜欢使用它们,因为它需要我知道导航属性的名称,这不够通用.
我可以找到关系正在改变的相关对象,但当然这些相关对象中的值没有改变,所以这也没有任何帮助.
在使用ChangeTracker的SaveChanges期间,我是否有一些干净的方式来跟踪实体之前的关系?
下面是我正在处理的代码部分:
public override int SaveChanges()
{
List<AuditObject> auditTrailList = new List<AuditObject>();
foreach (DbEntityEntry entity in ChangeTracker.Entries().Where(obj => { return obj.State == EntityState.Added || obj.State == EntityState.Modified || obj.State == EntityState.Deleted; }))
{
if (!(entity.Entity is AuditObject))
{
AuditObject auditObject = new AuditObject();
auditObject.Id = Guid.NewGuid();
auditObject.RevisionStamp = DateTime.Now;
auditObject.UserName = HttpContext.Current.User.Identity.Name;
auditObject.EntityType = Utilities.GetCleanClassNameIfProxyClass(entity.Entity.GetType().Name);
if (entity.State == EntityState.Added)
auditObject.Action = EntityState.Added.ToString();
else if (entity.State == EntityState.Modified)
auditObject.Action = EntityState.Modified.ToString();
else if (entity.State == EntityState.Deleted)
auditObject.Action = EntityState.Deleted.ToString();
DbMemberEntry t1 = entity.Member("RelatedWebObjects");
// cannot find original relationship collection...
DbCollectionEntry t2 = entity.Collection("RelatedWebObjects");
// cannot find original relationship collection...
if (entity.State == EntityState.Added || entity.State == EntityState.Modified)
{
XDocument currentValues = new XDocument(new XElement(auditObject.EntityType));
foreach (string propertyName in entity.CurrentValues.PropertyNames)
{
currentValues.Root.Add(new XElement(propertyName, entity.CurrentValues[propertyName]));
}
auditObject.NewData = Regex.Replace(currentValues.ToString(), @"\r\n+", " ");
}
if (entity.State == EntityState.Modified || entity.State == EntityState.Deleted)
{
XDocument originalValues = new XDocument(new XElement(auditObject.EntityType));
foreach (string propertyName in entity.OriginalValues.PropertyNames)
{
originalValues.Root.Add(new XElement(propertyName, entity.OriginalValues[propertyName]));
}
auditObject.OldData = Regex.Replace(originalValues.ToString(), @"\r\n+", " ");
}
auditTrailList.Add(auditObject);
}
}
foreach (var audit in auditTrailList)
this.AuditObjects.Add(audit);
return base.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
Lad*_*nka 13
这有点困难.首先,您必须区分EF提供的两种类型的关系:
现在,如果您想知道外键关联的先前值,则只需跟踪已公开外键属性的从属实体中的更改 - 这与跟踪任何其他属性更改完全相同.
如果要跟踪独立关联中的更改,情况将变得更加困难,因为DbContext API 不提供跟踪它们的操作.您必须恢复到ObjectContextAPI及其ObjectStateManager.
ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext;
foreach (ObjectStateEntry entry = objectContext.ObjectStateManager
.GetObjectStateEntries(~EntityState.Detached)
.Where(e => e.IsRelationship))
{
// Track changes here
}
Run Code Online (Sandbox Code Playgroud)
现在您可以访问ObjectStateEntry该关系的实例.这些实例永远不应该有状态Modified.他们将两种Added,Deleted或者Unchanged因为"修饰"老关系的删除和添加一个新的处理.ObjectStateEntry还包含CurrentValues和OriginalValues集合.这些集合还应包含两个项目,每个项目代表EntityKey关系一侧的实体.
由于 EF 更改跟踪图表中的每个对象,因此您始终可以将图表中的任何实例传递给更改跟踪器,它将为您提供更改跟踪值。例如,以下代码将获取 AuditObject 导航属性的原始/当前值:
DbMemberEntry t1 = entity.Member("RelatedWebObjects");
// cannot find original relationship collection....
AuditObject currentAuditObject = (AuditObject) entity;
var currValues = this.Entry(currentAuditObject.RelatedWebObjects).CurrentValues;
var orgValues = this.Entry(currentAuditObject.RelatedWebObjects).OriginalValues;
Run Code Online (Sandbox Code Playgroud)
或者,在处理集合类型导航属性时,您可以应用相同的技巧:
DbCollectionEntry t2 = entity.Collection("RelatedWebObjects");
// cannot find original relationship collection....
foreach (WebObject item in currentAuditObject.RelatedWebObjects)
{
var currValues = this.Entry(item).CurrentValues;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
9305 次 |
| 最近记录: |