【发布时间】:2015-06-02 22:54:05
【问题描述】:
我们遇到了以下情况:我们更改了实体的属性,但PropertyChanged 事件没有触发。我们正在将此逻辑作为保存的一部分执行,因此问题似乎是 DevForce 在保存期间对此类事件进行排队的方式。
查看 LoadingBlock.Dispose() 的代码,我看到了:
public void Dispose()
{
this._entityManager.FireQueuedEvents();
this._entityManager.IsLoadingEntity = this._wasLoadingEntity;
}
在更改IsLoadingEntity 属性之前,您会触发排队的事件。这意味着在 FireQueuedEvents 期间生成的任何新事件都将被排队(因为IsLoadingEntity 仍然是真的),但排队的事件将永远不会被触发,因为我们已经触发了排队的事件(我们知道)。似乎 DevForce 应该在触发事件之前重置 IsLoadingEntity 标志。我认为这会解决我们的问题。
这里有一些代码可能有助于解释我们的案例。我将使用 Merge 调用而不是 SaveChanges,因为它更容易在单元测试中使用:
//Create the main Entity Manager and a test entity
var em = new EntityManager();
var entity = new MyEntity {SID = 123};
em.AttachEntity(entity);
//Create a second copy of the entity and another Entity Manager - this is just so
// we can trigger a merge and see the bad behavior
var copy = new MyEntity { SID = 123, MergeCount = 20 };
var em2 = new EntityManager();
em2.AttachEntity(copy);
//This code is a bit contrived but it's similar to what we are doing in our actual app
em.EntityChanged += (sender, args) =>
{
//If it is a MyEntity that changed and it was from a Merge, increment the MergeCount property
var e = args.Entity as MyEntity;
if (e != null && args.Action == EntityAction.ChangeCurrentAndOriginal)
{
e.MergeCount++;
}
};
//Set up a PropertyChanged event handler to see what properties got changed (according to INotifyPropertyChanged)
var propertiesChanged = new List<string>();
entity.PropertyChanged += (sender, args) => { propertiesChanged.Add(args.PropertyName); };
//Merge the copy entity
em2.CacheStateManager.GetCacheState().Merge(em, RestoreStrategy.Normal);
//At this point, the MergeCount property will be 21 - as expected
Assert.AreEqual(21, entity.MergeCount);
//We should have seen a PropertyChanged event for MergeCount since we changed the property (it was 20 and we set it to 21)
Assert.IsTrue(propertiesChanged.Contains("MergeCount"));
//In the debugger, if we look at em._queuedEvents, we'll see some items in there. One of the items is the PropertyChanged event
// for MergeCount. It 'fired' but was queued...and it will be queued forever because the LoadingBlock is long gone.
我发现我可以从一个空的实体管理器中执行另一个合并,这将导致之前排队的事件触发。在我们遇到这种情况的一种情况下,这是一个不错的解决方法。但我担心我们可能会在其他地方遇到这个问题,而这种解决方法对我们不起作用。
【问题讨论】: