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 应用程序中使用带有柴油的计时功能

Rust,Windows 10:柴油机不工作,柴油机设置不提供输出

柴油机编译挂在 Lightsail 上

是否可以在柴油中使用没有主键的表?锈

如何使用柴油在 sqlite 中进行 upsert?

如何使用锈柴油创建新数据库?