F# 从数据库返回的Product对象列表提取指定属性生成新列表
问题分析&解决方法
你代码的核心问题有三点:
session.Query返回的集合大概率是弱类型的IEnumerable<object>(ORM框架会把查询结果装箱为object),不是强类型的Product集合,所以直接访问属性会提示类型不匹配- 误用了
List.collect,这个函数的作用是把每个元素映射为集合后再扁平化合并,你只需要做属性映射用map类函数即可 - 第二版的模式匹配逻辑错误:没有提前定义
ProductClass可区分联合的前提下不能这么匹配,None是Option类型的空值case,和object类型不兼容,ignore返回unit也无法和元组返回值统一类型
步骤1:转强类型集合
如果能确定所有查询结果都是Product<IProductVariant>类型,直接用Seq.cast转换:
let strongTypedProducts = session.Query<Product<IProductVariant>>("where id < 1000") |> Seq.cast<Product<IProductVariant>>
如果存在非目标类型的结果需要过滤,用Seq.choose做安全类型转换:
let strongTypedProducts = session.Query<Product<IProductVariant>>("where id < 1000") |> Seq.choose (fun item -> // 用类型测试模式匹配Product类型 match item with | :? Product<IProductVariant> as p -> Some p | _ -> None )
步骤2:映射指定属性
用Seq.map筛选需要返回的属性即可,如果要返回给前端推荐用匿名记录,序列化后前端能直接拿到带字段名的对象:
// 返回元组格式 let returnValue = strongTypedProducts |> Seq.map (fun p -> (p.ID, p.Name)) |> List.ofSeq // 返回匿名记录格式(更适合前端接口返回) let returnValue = strongTypedProducts |> Seq.map (fun p -> {| ID = p.ID; Name = p.Name |}) |> List.ofSeq
注意:F#的
List模块只能处理原生F#不可变列表,ORM返回的.NET通用集合优先用Seq模块处理,需要转F#列表最后调用List.ofSeq即可。
内容的提问来源于stack exchange,提问作者silvercoins
相关产品推荐
相关产品推荐

