EF Core LINQ 使用反射获取属性值大幅降低查询速度 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yuhangch
2.53D
V2EX    .NET

EF Core LINQ 使用反射获取属性值大幅降低查询速度

  •  
  •   yuhangch 2022-04-11 20:13:19 +08:00 3484 次点击
    这是一个创建于 1347 天前的主题,其中的信息可能已经有所发展或是发生改变。

    多个表,不同的字段,一个业务他们处理逻辑相同

    所以想用反射来减少点代码量,但是使用反射来获取值速度下降的厉害 ~ x5

    async List<object> SelectValues<T>(IQueryable<T> queryable, string fieldName) where T : class { var type = typeof(T); var field = type.GetProperty(fieldName); if (field == null) throw new ArgumentNullException(nameof(fieldName)); var get = (T a) => (double?) field.GetValue(a); return queryable .Select(t => new { V = get(t) //非常慢 // V = t.field 速度正常 }).ToList(); } 

    有没有什么优化方案,或者不应该这么干?

    10 条回复    2022-04-12 09:43:14 +08:00
    leeg810312
        1
    leeg810312  
       2022-04-11 20:25:54 +08:00 via Android
    在集合循环执行反射不合适,可以替换 fieldname 参数为 lambda 表达式参数
    hackfly
        2
    hackfly  
       2022-04-11 20:47:50 +08:00
    定义一个泛型类,定义一个查询接口,每个表类派生,都实现各自查询接口,这样也多不了多少代码,就是多几个实力类
    moen
        3
    moen  
       2022-04-11 21:08:27 +08:00
    GetProperty/GetValue 这一套下来慢是必然的。一种解决方案就是使用表达式树,生成一个获取 t.prop 的委托;第二种就是使用 Source Generator 把用到的 T 的所有属性的获取代码都生成出来,0 反射
    killergun
        4
    killergun  
       2022-04-11 21:11:39 +08:00
    你看看官方的集合扩展 Select 是怎么实现的,根本就不需要反射
    userforg2021
        5
    userforg2021  
       2022-04-11 21:55:24 +08:00
    你这个需求。。。不就是 Select 的功能吗。。。。
    Rocketer
        6
    Rocketer  
       2022-04-11 23:09:07 +08:00
    t.field 会被直接翻译成 sql 语句在数据库中执行,而反射只能把数据先取到内存中,转化成对象,再反射取值,当然慢。

    更何况反射本身就慢。

    你这个需求,可以使用 Dynamic LINQ 来替换 Select 里面的内容,从而使操作能最终变成 sql 语句。

    官方例子就有: https://dynamic-linq.net/basic-simple-query
    beginor
        7
    beginor  
       2022-04-11 23:24:06 +08:00
    这个只需要对 Linq 做一点儿扩展就够,就是构建简单的取属性的 lambda 表达式传进去就行了, 甚至都不需要第三方类库, 给你看一个动态添加排序的例子

    https://github.com/beginor/appfx/blob/master/src/Core/LinqExtensions.cs#L64
    ShareDuck
        8
    ShareDuck  
       2022-04-12 09:04:04 +08:00
    调用的时候,同样都要输入 fieldName ,也没有降低代码量吧。
    coder001
        9
    coder001  
       2022-04-12 09:22:02 +08:00
    在 IQueryable<T>用 AutoMapper 的 Projection 方法,可以生成查询表达式实现按需 Select
    yuhangch
        10
    yuhangch  
    OP
       2022-04-12 09:43:14 +08:00
    @leeg810312
    @hackfly
    @moen
    @killergun
    @userforg2021
    @Rocketer
    @beginor
    感谢各位,先用 dynamic linq 顶一下,后面有时间了再看看表达式树的方法
    (头天晚上焦头烂额,发个帖第二天早上解决了,v 站 up
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2659 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 15:08 PVG 23:08 LAX 07:08 JFK 10:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86