如何在EF中使用异步方法加速加载数据?

时间:2019-05-15 19:18:27

标签: c# .net entity-framework mvvm

到目前为止,我的列表上有很多数据要加载。当我使用普通(同步)方式加载数据时,加载所有数据大约需要20秒。我做了这种异步方法,现在我需要大约7秒钟来加载。 我想知道是否有一种方法可以加快它的速度,例如,打开屏幕后立即加载前20张卡,然后执行其他所有操作?到目前为止,这是我的代码。

public async Task<List<CardObject>> GetCardsAsync()
{
    using (var context = new MyCARDEntities())
    {
        return await context.Card
            .Include(f => f.Person)
            .Include(k => k.CardType)
            .Where(arg => arg.LastAction != "D" && arg.PERSON_ID != null)
            .Select(k => new CardObject()
            {
                    Id = k.Id,
                    UID = k.UID,
                    Person = new PersonBasicObject()
                    {
                        Id = k.PersonBasicObject.Id,
                        OIB = k.PersonBasicObject.OIB,
                        Name = k.PersonBasicObject.Name,
                        LastName = k.PersonBasicObject.LastName
                    }
            })
            .ToListAsync();
    }
}

这是在viewModel中

private async void LoadCards()
{
    var cards = await repKartica.GetCardsAsync();
    CardLst = new ObservableCollection<CardObject>(cards);
}

private ObservableCollection<CardObject> _CardLst;
public ObservableCollection<CardObject> CardLst 
{
    get => _CardLst;
    set
    {
        _CardLst= value;
        RaisePropertyChanged(() => CardLst);
    }
}

1 个答案:

答案 0 :(得分:0)

使方法异步并不能使方法更快,它只是允许方法放弃执行线程以允许其他代码运行。这可以使代码更具响应性,但不会更快地检索特定数据。

首先,如果可以避免加载大量数据,则不是一个好主意。客户是否需要一次查看所有全部数据,或者一次可以将其分页到20张卡片的页面中?如果它是或可以分页的,则考虑使用分页集合,该集合可以查询特定数据页(利用.Skip().Take()),一次只收回20条左右的记录(可见)页面更改。

下一步是查看正在执行的查询。对数据库运行探查器,例如ExpressProfiler,并捕获EF正在运行的SQL。在企业管理器中执行这些查询的副本以获取执行计划,并查看是否有索引建议。

其他提示:使用.Select()时不需要使用.Include()。 Select将生成查询以自动从相关实体中提取。

PersonBasicObject和CardObject是您的实体定义吗?如果是这样,那么这些实体中有多少个字段将未被此Select填充?理想情况下,您应该使用专用的视图模型,而不要传递实体。通过使用Select()填充实体来有选择地填充数据,就意味着它不是实体的完整表示,从而构成了不是实体的实体。由于变量仍会占用内存但没有填充,因此效率可能很低,并且会产生误导并导致错误,因为您将拥有期望实体的代码,并且可能会被调用/重用,但随后却要处理“真实的”完整实体相对于这样加载的不完整实体。实体的唯一目的应该是代表数据状态,而不是为视图状态传输。