【问题标题】:Entity Framework 6 avoid repetitive loadingEntity Framework 6 避免重复加载
【发布时间】:2016-07-04 16:44:15
【问题描述】:

我有一个简单的 C# MVVM WPF 应用程序,其中有一个 MainWindow,其中包含一个 Ribbon 和一个 ContentControl。基于功能区操作,我切换到不同的用户控件并在 ContentControl 中显示。

要在 ViewModel 中加载数据,我基本上是这样做的:

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;
    }
}

现在,每次我将此 ViewModel 作为 DataContext 显示 UserControl 时,都会调用 LoadMethod。

有什么办法可以避免这种情况吗?因为_ctx.Products.Load()需要一些很长的时间(对于 11K 记录)并且使用 _ctx.Products.Local 访问 ObservableCollection 也非常慢。

我喜欢为每个 UserControl 和 .LocalCollection 使用 DataContext,因为它很容易使 UI 与数据库保持同步。但如果有更好的方法,请告诉我。

我对 EF 和 MVVM/WPF 非常陌生,因此非常感谢您的帮助!

P.S.:我使用的是 EF 6,Database First 和 SQL Server 2014

【问题讨论】:

  • 第一个问题是:为什么要加载所有记录?
  • 因为我有一个 DataGrid,用户可以在其中编辑记录,并且至少没有简单的解决方案可以在 WPF DataGrid 中实现分页 afaik...
  • 有几种方法可以提高性能,但这取决于您的应用程序的逻辑。您可以在数据检索中添加一些过滤器,或者您可以将数据检索放在更高级别(例如,在页面的根目录而不是用户控件上,使其成为某种静态/单例)。另一个细节:我认为没有必要在 DbContext Set 实例上调用 .Load() 方法。另外:您能否向我们展示您的实体框架配置(例如延迟加载)
  • 需要调用.Load()方法!我根本没有更改任何 EF 配置,因为我使用数据库优先延迟加载应该默认启用!?

标签: c# wpf mvvm entity-framework-6


【解决方案1】:

由于您提到这是一个“简单”的桌面应用程序,因此您有可能正在创建一个由单个用户编辑数据的应用程序。如果这是您的意图,请允许我建议 MVVM 的替代方案。 MVVM 是一个非常好的架构,但对于简单的桌面应用程序来说可能有点过头了。

这是我使用的另一种解决方案,它非常适用于使用 EF Database First 的单用户应用程序:

主窗口使用单个DBContext,所有UserControls,并有一个“保存”按钮/菜单项来提交所有更改。您还可以在用户尝试退出并提示先保存时检查更改。此外,如果您的对象实现了INotifyPropertyChangeObservableCollections,您在一个位置的更改会反映在您的应用程序的其他位置。有多种方法可以使这个DBContext 在整个应用程序中可用,例如使用单例模式,或者简单地创建一个静态类并将其放置在其中(作为公共静态成员)。然后让所有控件都使用这个实例。

至于实现INotifyPropertyChangeObservableCollections,您有两种选择: 选项 1) 首先使用 Database 和 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: 请参阅:Kolya Evdokimov 的 答案:How can I change an Entity Framework ICollection to be an ObservableCollection?, 一处改动:在.ttNavigationProperty函数中,将ICollection改为ObservableCollection

更改.tt 后,右键单击.tt 文件并选择运行自定义工具。
完成后,您创建的 EF 类将实现 INotifyPropertyChange,并具有 ObservableCollections 用于关联。这些应该准备好在 WPF 控件上实现DataBindingUserControl 的更改会反映在应用程序的其他位置,因为底层模型使用 INotifyPropertyChangeObservableCollections

我会在此处为您粘贴我的 .tt 文件,但它太大了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多