被 ORM 折磨, sql 1 分钟写好, ORM 想了一个小时,没写出来😭

2021-09-14 15:24:34 +08:00
 wuwukai007

救救孩子吧

select d.id,d.created_time,(select count(*) from word where word.dictionary_id=d.id)
    as word_count,
       (select account from user where user.id = d.creator_id) as username,
       d.dictionary_name
        from dictionary
    as d where d.thesaurus_name='professional'
6908 次点击
所在节点    Python
39 条回复
JKeita
2021-09-14 15:39:56 +08:00
那就别用呗,orm 性能又不是说有多好。又不直观。维护又麻烦。
AoEiuV020
2021-09-14 15:40:18 +08:00
会 sql 的话 orm 也都能直接执行 sql 的吧,或者能随便写写转成 sql 对比一下再调整,
kingfalse
2021-09-14 15:44:21 +08:00
不要为了用而用
Hstar
2021-09-14 15:45:03 +08:00
里面那个 select count(*) from word where word.dictionary_id=d.id 子查询不好写,建议先查了变成一个字典再拼接
honkki
2021-09-14 15:45:24 +08:00
orm 也可以直接执行 sql 原生语句的呀
Pursue9
2021-09-14 15:49:55 +08:00
你这样用 SQL,真的不怕数据库蹦吗

建议先查` dictionary `
```sql
SELECT
d.id,
d.created_time
FROM dictionary AS d
WHERE d.thesaurus_name='professional'
LIMIT 1000
```
再去查 word_count user
```sql
SELECT id,COUNT(1)
FROM word_count
WHERE id IN ()
```

```sql
SELECT account FROM `user`
WHERE id IN ()
```

然后返回的结果再用程序处理后返回
qW7bo2FbzbC0
2021-09-14 15:52:23 +08:00
不要为了用而用
thetbw
2021-09-14 15:52:33 +08:00
如果数据量不是很大的话分成三个查询如何,
第一个查询查 select d.id,d.created_time d.dictionary_name from dictionary
as d where d.thesaurus_name='professional'
后两个查询分别为上面的子查询,然后组装数据
wuwukai007
2021-09-14 16:23:26 +08:00
顿悟了
word_count = select(func.count(Word.id)).where(Word.dictionary_id==Dictionary.id).label('word_count')
username = select(User.account).where(User.id == Dictionary.creator_id).as_scalar().label('username')
s = select(Dictionary.created_time,word_count,username).where(Dictionary.thesaurus_name=='professional')
Latin
2021-09-14 18:01:37 +08:00
@wuwukai007 这不还是一次查询分了三次吗 (狗头
Rwing
2021-09-14 18:07:51 +08:00
不是我说。。。这也叫 ORM 吗。。。。不就是把 sql 关键字替换成了函数。。。。。。
clf
2021-09-14 18:10:56 +08:00
换个 ORM 吧,理想的 ORM 应该是封装了单表查询的方法,多表通过注解关联两个类的字段或者是配置文件配置,进一步的甚至可以用 lambda 方法来构造跨表查询。
Rwing
2021-09-14 18:23:52 +08:00
优秀的 orm 应该是这样的

from dict in db.dictionary
where dict.Thesaurus_name == 'professional'
select new
{
dict = dict,
wordCount = dict.Word.Count(),
userName = dict.User.Name
};

或者 S
db.dictionary
.Where(d => d.Thesaurus_name == 'professional')
.Select(d =>{
new {
dict = d,
wordCount = d.Word.Count(),
userName = d.User.Name
}
})
Pursue9
2021-09-14 18:41:47 +08:00
@Rwing EFCore 啊,应该除了 C# /F#,别的语言应该实现不了这种 linq 这种伪 SQL
Trim21
2021-09-14 18:48:08 +08:00
你可以直接执行 SQL 然后把结果序列化成 ORM 的类啊…
wuwukai007
2021-09-14 18:50:14 +08:00
@Trim21 @AoEiuV020 @JKeita 直接用 sql 在参数不固定时,会有恶心的 最后一个 and 的问题,要处理 where 1= 1 这种
Thinklong
2021-09-14 19:17:49 +08:00
所有连表查询都应该被干掉,再好的 ORM 也不是你作案的工具
spediacn
2021-09-14 20:00:50 +08:00
牛叉组件都是绕开 ORM 的,比如 ms 的 identity,直接底层调用存储过程
cp19890714
2021-09-14 20:14:37 +08:00
1. 简单查询用 ORM, 稍复杂的都直接写 sql
2. 把复杂查询拆成多个简单查询.
kevinonepiece
2021-09-14 20:20:01 +08:00
@Pursue9 连表查只用一次 MySQL 连接,分开查得三次连接,我之前把三次简单查询合并成一次,速度快了,所以该怎么权衡呢?

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

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

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

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

© 2021 V2EX