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

2022-04-11 20:13:19 +08:00
 yuhangch

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

所以想用反射来减少点代码量,但是使用反射来获取值速度下降的厉害 ~ 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();
}

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

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

更何况反射本身就慢。

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

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

https://github.com/beginor/appfx/blob/master/src/Core/LinqExtensions.cs#L64
ShareDuck
2022-04-12 09:04:04 +08:00
调用的时候,同样都要输入 fieldName ,也没有降低代码量吧。
coder001
2022-04-12 09:22:02 +08:00
在 IQueryable<T>用 AutoMapper 的 Projection 方法,可以生成查询表达式实现按需 Select
yuhangch
2022-04-12 09:43:14 +08:00
@leeg810312
@hackfly
@moen
@killergun
@userforg2021
@Rocketer
@beginor
感谢各位,先用 dynamic linq 顶一下,后面有时间了再看看表达式树的方法
(头天晚上焦头烂额,发个帖第二天早上解决了,v 站 up

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/846359

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX