我目前正在开发一个ASP.NET Core Web API.当用户正在查看的实体发生更改时,需要通知客户端更新其数据.
为此,我需要检测何时对特定父实体进行了更改.我通过判断在覆盖上下文的SaveChanges
方法时是否将Entry(Parent).State
设置为任何值而不是未更改来完成此操作:
public override int SaveChanges()
{
foreach(var p in Parents)
{
if (Entry(p).State != EntityState.Unchanged)
{
// Notify client
}
}
return base.SaveChanges()
}
我的问题是,如果任何子对象发生更改,我还需要告诉客户端进行更新,但我似乎找不到一种方法来检测这一点.
S的Entry
‘属性(Entry().Properties
、.Navigations
等)都将子项显示为IsModified == false
,而更改跟踪器似乎也没有帮助.
编辑:我可以判断更改跟踪器的Entries
,并查看我正在查找的Parent
的ID是否设置为修改后的子项的外键,但我还需要能够检测子项的子项是否更改.如果与Parent
相关的任何内容发生更改,客户端需要更新其视图.
百龙的回答非常有帮助,尽管我不得不做了几处改动才能让它正常工作.我目前不能try 所有可能的情况,因为在编写本文时,API还没有完成,但就我测试的情况而言,它是有效的.它可能有点低效率或有错误,但对于任何寻找相同东西的人来说,它应该是一个足够的指针:
private void DetectAndNotifyChanges()
{
foreach(var p in Parents)
{
var pEntry = Entry(p);
if (pEntry.State != EntityState.Unchanged || HasChangesInChildren(p))
{
// Notify client
}
}
}
对于DetectAndNotifyChanges
,我判断每个父对象,并通知受更改影响的对象.
private List<dynamic> checkedEntries = new List<dynamic>();
private bool HasChangesInChildren(dynamic parent)
{
foreach(var navigationEntry in Entry(parent).Navigations)
{
if (navigationEntry is CollectionEntry collectionEntry)
{
collectionEntry.Load();
foreach(var child in collectionEntry.CurrentValue)
{
var childEntry = Entry(child);
if (!checkedEntries.Contains(childEntry))
{
checkedEntries.Add(childEntry);
if (childEntry.State != EntityState.Unchanged || HasChangesInChildren(child))
{
return true;
}
}
}
}
else if (navigationEntry is ReferenceEntry referenceEntry)
{
referenceEntry.Load();
dynamic childEntry = referenceEntry.EntityEntry;
if (!checkedEntries.Any(x => x.GetType() == childEntry.GetType() && x.Entity.Id == childEntry.Entity.Id))
{
checkedEntries.Add(childEntry);
if (childEntry.State != EntityState.Unchanged || HasChangesInChildren(childEntry.Entity))
{
return true;
}
}
}
}
return false;
}
然后,对于HasChangesInChildren
,我将参数更改为Dynamic,因为它先判断父对象,然后判断子对象,然后再判断子对象,等等,为referenceEntry
和collectionEntry
添加Load
,因为它们以前没有加载,并且通过排除任何以前判断过的对象来防止无限递归,使用checkedEntries
列表再次判断.