使用 OData Web Api 对数据传输对象进行嵌套筛选
Posted
技术标签:
【中文标题】使用 OData Web Api 对数据传输对象进行嵌套筛选【英文标题】:Nested filter on Data Transfer Object using OData Wep Api 【发布时间】:2013-09-25 13:45:40 【问题描述】:我有一个 wep api 项目使用 odata 使用数据,但我在使用 odata wep api 时遇到了一些问题。
当我执行那个查询时
/api/values?$top=50&$filter=Comments/Fortuneteller/FullName eq '一些字符串'
它给了我以下错误
"Message": "URI 中指定的查询无效。", "ExceptionMessage": "属性 'Fortuneteller' 的属性访问的父值不是单个值。属性访问只能应用于单个值。"
我不想从控制器返回实体对象。有没有办法通过 DTO 过滤实体?
我在我的项目中使用 Repository + Service 层模式,我的项目结构是这样的
api 控制器 服务 存储库 EF
api 控制器
[Queryable]
public IQueryable<FortuneDTO> Get()
return service.FiterBy((_ => true));
服务
public IQueryable<FortuneDTO> FiterBy(Expression<Func<tblFortune, bool>> filter)
return repository.List().Where(filter).Select(_ => new FortuneDTO
CreatedByFullName = _.aspnet_Users.FullName,
Id = _.FortuneId,
Comments = _.tblComment.Select(c => new CommentDTO
Id=c.CommentId,
Comment = c.Comment,
Fortuneteller = new FortunetellerDTO
FullName=c.aspnet_Users.FullName,
Id=c.aspnet_Users.UserId
).AsQueryable()
);
存储库
public virtual IQueryable<TEntity> List()
return context.CreateObjectSet<TEntity>();
DTO
public class FortuneDTO
public int Id get; set;
public string CreatedByFullName get; set;
public IQueryable<CommentDTO> Comments get; set;
public class CommentDTO
public int Id get; set;
public string Comment get; set;
public FortunetellerDTO Fortuneteller get; set;
public class FortunetellerDTO
public Guid Id get; set;
public string FullName get; set;
【问题讨论】:
【参考方案1】:正如异常消息告诉您的,您的查询无效。
/api/values?$top=50&$filter=Comments/Fortuneteller/FullName eq 'some string'
等价于linq表达式
fortuneDTOs.Where(f => f.Comments.Fortuneteller.FullName == "some string").Top(50)
如您所见,fortuneDTOs.Comments.Fortuneteller
不正确,因为 Comments 是一个集合,它没有名为“FullName”的属性。
您应该使用 Any/All 来过滤集合。例如,如果您要查找其中一位评论员是“某个字符串”的所有命运,您可以这样做
/api/values?$top=50&$filter=Comments/any(c: c/Fortuneteller/FullName eq 'some string')
如果你想找出所有的财富都是由一个评论员“一些字符串”创造的,你可以这样做
/api/values?$top=50&$filter=Comments/all(c: c/Fortuneteller/FullName eq 'some string')
【讨论】:
谢谢,我遇到了问题,但现在它给了我这个错误消息,我无法弄清楚它是什么意思 "Message": "An error has occurred.", "ExceptionMessage": " 'ObjectContent`1' 类型无法序列化内容类型 'application/json; charset=utf-8' 的响应正文。” 和内部异常“Message”:“发生错误。”,“ExceptionMessage”:“无法比较'System.Linq.IQueryable`1'类型的元素。只有原始类型(支持 Int32、String 和 Guid)和实体类型。” 如果我们想使用 contains 而不是 eq 怎么办?以上是关于使用 OData Web Api 对数据传输对象进行嵌套筛选的主要内容,如果未能解决你的问题,请参考以下文章
在没有实体框架的情况下创建 Odata Web API 应用程序
如何获取 OData 可查询 Web API 端点过滤器并从 DTO 对象映射它?
.Net Core 3.1 Web Api 的自定义 OData 日期时间序列化程序