如何从Entity Framework异步创建IEnumerable?Blazor DevExpress组件相关疑问
1. 关于扩展方法无需声明为async的理解是否正确?
完全正确。context.Skills.OrderBy(s => s.Name)返回的是IQueryable<Skill>(它实现了IEnumerable<Skill>接口),这仅仅是构建了查询表达式树,并没有触发实际的数据库操作。只有当后续枚举这个集合(比如组件渲染遍历数据、调用ToList()等)时,才会执行数据库查询。只有真正执行数据库读写的操作(如ToListAsync()、FirstOrDefaultAsync()这类直接触发查询的方法),才需要用async/await标记异步。
2. Blazor Server + DevExpress组件的异步加载方案
有没有办法实现异步?
有两种可行的方案:
- 提前在页面生命周期异步加载数据:
在Blazor页面的生命周期方法(比如OnInitializedAsync)中,先异步获取数据并存到本地变量,再将变量传给组件的Data属性。示例代码:
组件部分修改为:private List<Skill> _skills = new(); protected override async Task OnInitializedAsync() { _skills = await NoTrackingDbContext.Skills.OrderBy(s => s.Name).ToListAsync(); await base.OnInitializedAsync(); }<DxFormLayoutItem Caption="Your skills:" Field="@nameof(RegisterPageModel.Skills)" ColSpanMd="6"> <DxTagBox Data="@_skills" TextFieldName="@nameof(Skill.Name)" @bind-Values="@RegisterPageModel.Skills"/> </DxFormLayoutItem> - 使用DevExpress的异步数据绑定属性:
若你的DevExpress版本支持,部分控件提供了DataAsync属性,可以直接传入异步方法:<DxFormLayoutItem Caption="Your skills:" Field="@nameof(RegisterPageModel.Skills)" ColSpanMd="6"> <DxTagBox DataAsync="@(() => NoTrackingDbContext.Skills.OrderBy(s => s.Name).ToListAsync())" TextFieldName="@nameof(Skill.Name)" @bind-Values="@RegisterPageModel.Skills"/> </DxFormLayoutItem>
是否应该这么做?
非常推荐使用异步加载。Blazor Server的主线程负责处理用户交互,如果同步执行数据库查询,会阻塞主线程,导致页面失去响应(用户操作无反馈),尤其是查询耗时较长时,体验会极差。异步操作能释放主线程处理其他请求,提升应用的并发能力和响应性。
异步调用的优势
在Blazor Server场景下,异步加载的优势很明确:
- 避免UI阻塞:用户不会看到“假死”的页面,还可以配合加载指示器优化体验。
- 优化服务器资源:服务器可以同时处理更多用户请求,不会因单个同步查询占用线程。
内容的提问来源于stack exchange,提问作者David Thielen
相关产品推荐
相关产品推荐

