You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI+Vue.js应用Azure部署数据加载过慢求助

数据加载耗时过长的优化方案

我开发了基于.NET MAUI的移动端应用和Vue.js的Web端应用,两者均对接C#编写的API,数据库(SSMS)与API都部署在Azure平台。当前获取数据进行展示时耗时过长(约2-3分钟),求优化方案,相关代码如下:

Vue.js 前端代码

async fetchActivities() {
    try {
        const response = await fetch('/api/v1/Activities/all');
        if (!response.ok) {
            throw new Error(`Network response was not ok, status: ${response.status}`);
        }
        // 省略后续处理逻辑
    } catch (error) {
        console.error(error);
    }
}

.NET MAUI 客户端代码

httpclient.BaseAddress = new Uri(AppSettings.UrlApi);
httpclient.Timeout = TimeSpan.FromMinutes(2);
string oauthToken = await SecureStorage.Default.GetAsync(AppSettings.AuthToken);
httpclient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", oauthToken);
int loginUserId = Convert.ToInt32(await SecureStorage.Default.GetAsync(AppSettings.UserId));
var requestUri = "api/v1/Activities/all";

var response = await httpclient.GetAsync(requestUri);
var content = await response.Content.ReadAsStringAsync();

API 后端代码

Controller 部分

//[Authorize]
[ApiController]
[Route("api/v1/[controller]")]
public class ActivitiesController : ControllerBase
{
    private readonly IActivitiesRepository _activitiesRepository;
    private readonly IMessagesRepository _messagesRepository;
    private readonly IUsersRepository _usersRepository;
    private readonly IMapper _mapper;
    private readonly IImagesRepository _imagesRepository;

    public ActivitiesController(IActivitiesRepository activitiesRepository, IMapper mapper, IUsersRepository usersRepository, IMessagesRepository messagesRepository, IImagesRepository imagesRepository)
    {
        _activitiesRepository = activitiesRepository;
        _usersRepository = usersRepository;
        _mapper = mapper;
        _messagesRepository = messagesRepository;
        _imagesRepository = imagesRepository;
    }

    [HttpGet("{id}")]
    public async Task<ActionResult<ActivitiesEntity>> GetActivitiesbyIdAsync(int id)
    {
        ActivitiesEntity activitiesEntity = await _activitiesRepository.FindByIdAsync(id);
        return Ok(activitiesEntity);
    }

    [HttpGet]
    [Route("all")]
    public async Task<ActionResult<IEnumerable<ActivitiesModel>>> GetActivities()
    {
        IEnumerable<ActivitiesEntity>? activities = await _activitiesRepository.FindAllIncludingAsync(x => x.Images);
        var response = _mapper.Map<IEnumerable<ActivitiesModel>>(activities);
        return Ok(response);
    }
}

Repository 通用方法

public virtual async Task<IEnumerable<TEntity>> FindAllIncludingAsync(params Expression<Func<TEntity, object>>[] includeProperties)
{
    IQueryable<TEntity> query = _entities.AsNoTracking();
    foreach (var includeProperty in includeProperties)
    {
        query = query.Include(includeProperty);
    }
    return await query.ToListAsync();
}

具体优化建议

1. 数据库层优化

  • 添加索引:检查Activities表的主键、常用查询字段,以及Images表中关联Activities的外键字段,添加非聚集索引,提升关联查询速度。
  • 分页查询:如果Activities数据量较大,API端新增分页参数(page、pageSize),修改Repository方法实现分页:
    public async Task<IEnumerable<TEntity>> FindAllIncludingPagedAsync(int page, int pageSize, params Expression<Func<TEntity, object>>[] includeProperties)
    {
        IQueryable<TEntity> query = _entities.AsNoTracking();
        foreach (var includeProperty in includeProperties)
        {
            query = query.Include(includeProperty);
        }
        return await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync();
    }
    
    前端请求时传递分页参数,实现分段加载数据。
  • 减少不必要关联:如果前端不需要展示所有Images数据,可移除Include(x => x.Images),改为按需加载(比如点击活动详情时再请求对应图片)。

2. API层优化

  • 投影查询减少数据传输:直接通过Select返回前端需要的字段,避免序列化整个实体,减少数据包大小:
    [HttpGet("all")]
    public async Task<ActionResult<IEnumerable<ActivitiesModel>>> GetActivities()
    {
        var activities = await _activitiesRepository.FindAllIncludingAsync(x => x.Images)
            .Select(a => new ActivitiesModel
            {
                Id = a.Id,
                Title = a.Title,
                // 只映射前端需要的属性,省略不必要字段
                Images = a.Images.Select(img => new ImageModel { Id = img.Id, ThumbnailUrl = img.ThumbnailUrl })
            })
            .ToListAsync();
        return Ok(activities);
    }
    
  • 启用响应压缩:在API项目中配置Gzip或Brotli压缩,减少网络传输的数据量。
  • 监控性能瓶颈:通过Azure Application Insights跟踪API请求的耗时,明确是数据库查询慢还是网络传输慢。

3. 客户端优化

  • 缩短超时时间:将HttpClient的超时时间调整为更合理的值(比如30秒),避免无意义的长时间等待。
  • 数据缓存:前端将获取到的活动数据缓存到localStorage(Web端)或SecureStorage/内存(移动端)中,短时间内重复请求直接读取缓存。
  • 优化网络环境:确认Azure API和数据库的部署区域是否与目标用户区域接近,选择就近区域部署可降低网络延迟。

内容的提问来源于stack exchange,提问作者Chris Curt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 03:26:18