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

如何用Entity Framework和C#高效获取记录并优化GuestName加载

优化Booking加载性能方案

你的Load方法耗时20秒的核心原因是N+1数据库查询问题:循环中每个Booking都发起两次数据库请求(Any和GetName),如果有大量Booking,会产生数百次数据库调用,严重拖慢速度。下面是无需foreach循环的高效优化方案:

一、先修正EF实体关联(推荐方案)

给数据库实体Data.Tables.Booking添加Guest导航属性,让EF能直接关联查询:

[Table("Bookings")]
public class Booking : ITrackable
{
    // 原有属性保持不变
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public int GuestId { get; set; }

    // 添加Guest导航属性,指定外键关联
    [ForeignKey("GuestId")]
    public virtual Guest Guest { get; set; }

    // 其他原有属性...
}

二、配置AutoMapper映射GuestName

修改你的AutoMapper配置,让它直接从导航属性映射GuestName(假设Guest实体有Name属性):

public class MappingProfile : Profile
{
    public MappingProfile()
    {
        CreateMap<Data.Tables.Booking, Booking>()
            // 从关联的Guest实体中获取Name赋值给GuestName
            .ForMember(dest => dest.GuestName, opt => opt.MapFrom(src => src.Guest.Name));
    }
}

三、优化Load方法(一次性查询所有数据)

使用EF的Include预加载Guest数据,避免循环查询:

public List<Booking> Load(int roomId)
{
    var result = _context.Bookings
                         // 预加载关联的Guest数据,一次性从数据库取出
                         .Include(b => b.Guest)
                         .Where(b => b.RoomId == roomId)
                         .Select(b => _mapper.Map<Booking>(b))
                         .ToList();

    return result;
}

备选方案:不修改实体,用Join查询

如果不想修改实体结构,可以直接用Join方式一次性关联查询:

public List<Booking> Load(int roomId)
{
    var result = _context.Bookings
                         .Join(
                             _context.Guests,
                             booking => booking.GuestId,
                             guest => guest.Id,
                             (booking, guest) => new { Booking = booking, GuestName = guest.Name }
                         )
                         .Where(x => x.Booking.RoomId == roomId)
                         .Select(x => 
                         {
                             var model = _mapper.Map<Booking>(x.Booking);
                             model.GuestName = x.GuestName;
                             return model;
                         })
                         .ToList();

    return result;
}

额外优化建议

  1. 添加数据库索引:给Bookings.RoomId和Bookings.GuestId字段添加索引,加速查询过滤和关联。
  2. 缓存Guest数据:如果Guest信息不频繁更新,可以用内存缓存(如IMemoryCache)缓存Guest的Id-Name映射,进一步减少数据库查询。
  3. 移除冗余判断:原代码中的_context.Guests.Any()完全多余,若数据库有外键约束,GuestId必然对应有效Guest,直接获取Name即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:55:35