2015-06-02 31 views
1

我們遇到了更改我們實體上的屬性但PropertyChanged事件未觸發的情況。我們正在將此邏輯作爲Save的一部分,因此問題似乎就像DevForce在Save中排隊這樣的事件。如果DevForce在調用FireQueuedEvents期間排隊等候,並不總是觸發排隊事件

看的LoadingBlock.Dispose()的代碼,我看到:

public void Dispose() 
{ 
    this._entityManager.FireQueuedEvents(); 
    this._entityManager.IsLoadingEntity = this._wasLoadingEntity; 
} 

還有就是你火更改IsLoadingEntity屬性之前排隊的事件中的競爭條件存在。這意味着任何在FireQueuedEvents期間生成的新事件都將排隊(因爲IsLoadingEntity仍然是真的),但排隊後的事件將永遠不會被解僱,因爲我們已經釋放了排隊的事件(我們知道的)。似乎DevForce應該在觸發事件之前重置IsLoadingEntity標誌。我認爲這將解決我們的問題。

這裏有一些代碼可能有助於解釋我們的情況。我將使用一個合併,而不是調用的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. 

我發現我可以做其他的合併從空的實體管理器,這將導致先前排隊事件發生。在我們遇到這種情況的情況下,這是一個好的解決方法。但是我擔心我們可能會遇到其他地方遇到這個問題,該解決方法對我們不起作用。

回答

1

你說得對,IsLoadingEntity標誌應該在Dispose邏輯開始時被清除,我們將爲此打開一個錯誤報告。

如果您能夠使用EntityChanging事件而不是EntityChanged,這也可能是一種解決方法。更改事件未排隊,因此處理程序的執行會導致在處理LoadBlock之前處理PropertyChanged事件。

+0

我們在'EntityChanged'中有很多邏輯,所以我現在很害怕改變它。就目前而言,我們在進行保存之後用空的合併方式對其進行了黑客入侵,並且工作正常。但是我們期待這個正式版本能夠得到修復。謝謝! –

+0

是否有任何有關此修復程序何時可用的估計值。我正在調試另一個我認爲可能是由這種奇怪的競爭條件引起的問題。我希望能夠在應用修復程序後測試我的用例,因爲我希望修復能夠一箭雙鵰解決問題。 –

+0

下一個版本應該在未來2-3周。這個問題已經得到解決,但假期延遲了發佈。 –