铁锈-我可以使这个dsl​​ :: find函数更通用吗?

问题描述

我有一个函数使用柴油根据给定的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,但我不确定如何使该调用泛型接受任何类型。我知道有类型参数,但我认为这不行

解决方法

我通常建议不要使柴油发动机变得更通用,因为这会导致非常复杂的特质界限。通常,您永远都不希望在应用程序代码中执行此操作。 (对于需要通用的库而言,这是另一回事)。我通常将情况与普通SQL进行比较。例如,如果有人抱怨users::table.find(pk)感觉像重复,请问自己以下问题:您是否认为SELECT … FROM users在相应的查询SELECT … FROM users WHERE id = $中重复。 (dsl的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的类型不能由编译器推断出来,因此从代码大小的角度来看,此解决方案不是“简单”,而不仅仅是使其不通用。