2016-07-04 51 views
0

我有一個簡單的C#MVVM WPF應用程序,其中有一個MainWindow存放一個Ribbon和一個ContentControl。基於功能區操作,我切換到不同的用戶控件並在ContentControl中顯示。實體框架6避免重複加載

要加載視圖模型內部的數據我基本上做到這一點:

public class ProductsViewModel : BaseViewModel 
{ 
    public CollectionViewSource ProductsCollection { get; private set; } 
    private MyDataContext _ctx; 

    public ProductsViewModel() 
    { 
     ProductsCollection = new CollectionViewSource(); 
     _ctx = new MyDataContext(); 

     Load() 
    } 

    public void Load() 
    { 
     _ctx.Products.Load(); 
     ProductsCollection.Source = _ctx.Products.Local; 
    } 
} 

現在Load方法被調用每次我展示這個視圖模型作爲DataContext的用戶控件。

有什麼辦法可以避免這種情況?因爲_ctx.Products.Load()需要一些嚴重的時間(對於11K記錄)並且訪問ObservableCollection時_ctx.Products.Local也很慢。

我喜歡爲每個UserControl和.Local集合使用DataContext,因爲它很容易讓UI與數據庫保持同步。但如果有更好的方法,請讓我知道。

我對EF和MVVM/WPF非常陌生,所以非常感謝每一個幫助!

P.S:我使用EF 6,數據庫首先使用SQL Server 2014

+0

第一個問題是:爲什麼要加載所有記錄? –

+0

因爲我有一個DataGrid,用戶可以在其中編輯記錄,並且至少沒有簡單的解決方案在WPF DataGrid中實現分頁afaik ... – CeOnSql

+0

有幾種方法可以提高性能,但它取決於您的應用程序的邏輯。您可以在數據檢索中添加一些過濾器,或者可以將數據檢索放在更高級別上(例如,在頁面的根目錄而不是用戶控件上,使其成爲某種靜態/單態)。只是另一個細節:我不認爲你需要在DbContext Set實例上調用.Load()方法。另外:你能告訴我們你的實體框架配置(例如延遲加載) – hbulens

回答

0

既然你提到這是一個「簡單」的桌面應用程序,還有你創建一個由單個用戶編輯數據的應用程序的機會。如果這是您的意圖,請允許我建議MVVM的替代方案。 MVVM是一個非常好的體系結構,但對於簡單的桌面應用程序來說可能會被過度殺死。

這裏有一個替代的解決方案,我用的是非常適用於使用EF數據庫首先在單用戶應用程序:

使用單個DBContext你的主窗口,以及所有UserControls,並有一個「保存」按鈕/菜單項來提交所有更改。當用戶嘗試退出並提示首先保存時,您還可以檢查更改。另外,如果您的對象實施了INotifyPropertyChangeObservableCollections,則您在一個位置的更改會反映到您的應用中的其他位置。有多種方法可以在整個應用程序中使用這個DBContext,例如使用Singleton模式,或者簡單地創建一個靜態類並將其放置在那裏(作爲公共靜態成員)。然後讓所有的控件使用這個實例。

至於實施INotifyPropertyChangeObservableCollections,你有兩個選擇: 選項1)利用數據庫實現它先用的EntityFramework 4.這將創建對象從EntityObject,其中實現INotifyPropertyChange繼承。此外,協會實施爲EntityCollections,其實施AssociationChanged。所有這些對於簡單的 WPF應用程序都很有用。您可以將數據直接綁定到控件。這是創建功能完善的單用戶桌面應用程序的一種非常簡單的方法。這是我在幾乎每天都使用的應用程序中所做的。

選項2)首先用EF 6 DB實施,但修改爲支持INotifyPropertyChangeObservableCollections。默認情況下,EF 6創建默認情況下不可觀察的POCO(普通的舊CLR對象)。但是,可以修改創建過程以實現這些過程。關鍵是要修改T4模板,這是通過修改{yourmodelname}.tt文件完成的。我最近在基於EF4的應用程序上完成了這項工作,並且運行良好。以下是執行此操作的步驟:

找到您的{modelname}.tt文件,對其進行備份。

更新.tt添加INotifyPropertyChange。 請參閱:naskew的答案在這裏:Using INotifyPropertyChanged with Entity Framework 6 DbContext Generator

更新.TT使用ObservableCollections而不是HashSets: 參見:柯里亞葉夫多基莫夫的答案在這裏:How can I change an Entity Framework ICollection to be an ObservableCollection?, 有了一個變化:在.ttNavigationProperty功能,將ICollection更改爲ObservableCollection

更改.tt後,右鍵單擊.tt文件並選擇運行自定義工具。
完成後,您創建的EF課程將執行INotifyPropertyChange,並有ObservableCollections用於關聯。這些應該準備好在WPF控件上實現DataBinding。在一個UserControl變化在應用程序中的其他地方反映,因爲底層的模型使用INotifyPropertyChangeObservableCollections

我貼我的.tt文件爲你在這裏,但它太大了。