簡體   English   中英

在ViewModel中使用靜態DbContext的WPF應用程序

[英]WPF app with static DbContext in ViewModel

我正在使用MVVM,Code-First和存儲庫模式開發WPF應用程序。 我需要有一個后台任務,它處理來自客戶端的Web服務器請求並將新數據保存到數據庫中。

問題是每個ViewModel都有一個屬性(ObservableCollection),它獲取Repository.GetObservableCollection()。 因此每個ViewModel都有一個存儲庫實例,它具有相同的DbContext(因此在保存復雜實體時我不會得到DbException)。 這個DbContext長期存在,直到每個倉庫中的應用程序結束,並從MainViewModel注入到虛擬機的構造器。

當我從后台任務將新數據保存到數據庫時,GUI不會更新,因為我在那里使用不同的DbContext(我必須由於並發請求):

using (var db = new DbContextManager())
{
    var client = new Client();
    db.Client.Add(client);
    db.SaveChanges();
}

有兩種方法,我嘗試過:

  1. 在MainViewModel中設置DispatcherTimer,每隔2秒使用ViewModel.Repository.LoadAll為每個倉庫更新ViewModel。 每隔2秒就會落后於我的UI,但它確實有效。
  2. 將新數據保存到數據庫時,還要將實體添加到存儲庫。

    Application.Current.Dispatcher.Invoke(()=> {_ clientAdpository.Add(client);});

這樣,實體會立即出現在GUI中,但也有輕微的滯后(移動窗口時),我無法更新現有實體的屬性。

問題是如何重構這一點以允許GUI和后台與實體交互。 如何正確組合存儲庫和MVVM?

你使用綁定機制嗎? 您可以在更改后更新集合(假設您的VM實現了INotifyPropertyChanged接口)。

不要將ViewModel實體與DB DataContext 直接鏈接 您需要在ViewModel中定義ObservableCollection及其在XAML中的綁定。

之后,您將通過調用持久層中的函數來異步更新集合。 因此,最好使用LoadAsync ,或者將數據庫檢索包裝到Task中。 這種方法將起作用,因為await將捕獲UI線程的SynchronizationContext並將更新UI線程中的組件。

實際的DataContext必須隱藏在該持久層中,並且ViewModel必須保持未知

回復評論

如果我沒有將DbContext傳遞給ViewModels(后者又將其傳遞給它的存儲庫),我如何獲取存儲庫的上下文,所以我可以調用

point void LoadAll() { 
    context.Set<T>().Load(); 
} 

public ObservableCollection<T> GetObservableCollection() { 
    return context.Set<T>().Local; 
}

根據我的回答,ViewModel可以調用持久層函數來加載集合(甚至不需要從持久層返回的類型是可觀察的)。 關鍵是你不會返回void ,你可能會使用LoadAsync以便在將返回的數據分配給ViewModel屬性的基礎集合時await它。

所以我必須使用Dispatcher.Invoke與repos / viewmodels進行交互

不, 不要使用Dispatcher.Invoke存儲庫數據庫上下文進行交互。 與DB 異步進行交互。 請注意, Dispatcher.Invoke 適用於UI層。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM