问题描述
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
的类型不能由编译器推断出来,因此从代码大小的角度来看,此解决方案不是“简单”,而不仅仅是使其不通用。