Rust - 我可以让这个柴油 dsl::find() 函数更通用吗?
Posted
技术标签:
【中文标题】Rust - 我可以让这个柴油 dsl::find() 函数更通用吗?【英文标题】:Rust - Can I make this diesel dsl::find() function more generic? 【发布时间】:2021-01-01 15:48:06 【问题描述】:我有一个函数,它使用柴油根据给定的 ID 从数据库中获取对象:
fn get_db_site(pool: web::Data<Pool>, site_id: u32) -> Result<Site, diesel::result::Error>
let conn = pool.get().unwrap();
dsl::site.find(site_id).get_result::<Site>(&conn)
这个函数对于我想要运行它的每个表来说都是完全相同的,所以我希望把它放在它自己的 utils 文件中,这样我就不必每次都输入相同的东西。唯一的问题是为了调用我需要做的查找
crate::schema::site::dsl::site.find
我不确定如何使该调用泛型以采用任何类型。我知道有类型参数,但我认为这不会在这里工作
【问题讨论】:
【参考方案1】:我通常建议不要让柴油的东西更通用,因为这会很快导致非常复杂的特征界限。您通常永远不想在应用程序代码中执行此操作。 (对于需要通用的库来说,这是另一回事)。我通常将这种情况与普通 SQL 进行比较。例如,如果有人抱怨 users::table.find(pk)
感觉像重复,请问自己以下问题:您是否觉得 SELECT … FROM users
在相应的查询 SELECT … FROM users WHERE id = $
中重复。 (柴油dsl语句基本相同)。
因此,要回答您的实际问题,通用函数需要如下所示: (不确定我是否在没有测试的情况下完全正确)
fn get_db_thing<T, U, PK>(pool: web::Data<Pool>, primary_key: PK) -> Result<U, diesel::result::Error>
where T: Table + HasTable<Table = T>,
T: FindDsl<PK>,
U: Queryable<SqlTypeOf<Find<T, PK>>, Pg>
let conn = pool.get().unwrap();
T::table().find(primary_key).get_result::<U>(&conn)
如您所见,特征边界列表已经比仅在相应函数中内联加载要长得多。此外,在构造查询时添加的所有细节现在都需要作为通用函数参数。至少 T
的类型不能被编译器推断出来,所以从代码大小的角度来看,这个解决方案并不比不使其通用“简单”。
【讨论】:
以上是关于Rust - 我可以让这个柴油 dsl::find() 函数更通用吗?的主要内容,如果未能解决你的问题,请参考以下文章
无法在 Rust/Actix 应用程序中使用带有柴油的计时功能