使用OData Wep Api在数据传输对象上嵌套过滤器

emr*_*ran 18 c# odata asp.net-mvc-4 asp.net-web-api

我有一个wep api项目使用odata消耗数据,但我在使用odata wep api时遇到了一些问题.

当我执行该查询时

/ api/values?$ top = 50&$ filter = Comments/Fortuneteller/FullName eq'some string'

它给了我以下错误

"消息":"URI中指定的查询无效.","ExceptionMessage":"属性'Fortuneteller'的属性访问的父值不是单个值.属性访问只能应用于单个值."

我不想从控制器返回实体对象.有没有办法通过DTO过滤实体?

我在我的项目中使用Repository + Service层模式,我的项目结构就是这样

api controller < - > service < - > repository < - > EF

api控制器

    [Queryable]
    public IQueryable<FortuneDTO> Get()
    {
        return service.FiterBy((_ => true));
    }
Run Code Online (Sandbox Code Playgroud)

服务

    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()
        });
    }
Run Code Online (Sandbox Code Playgroud)

知识库

    public virtual IQueryable<TEntity> List()
    {
        return context.CreateObjectSet<TEntity>();
    }
Run Code Online (Sandbox Code Playgroud)

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; }
}
Run Code Online (Sandbox Code Playgroud)

Rag*_*nti 30

正如异常消息所示,您拥有的查询无效.

/api/values?$top=50&$filter=Comments/Fortuneteller/FullName eq 'some string'
Run Code Online (Sandbox Code Playgroud)

相当于linq表达式

fortuneDTOs.Where(f => f.Comments.Fortuneteller.FullName == "some string").Top(50)
Run Code Online (Sandbox Code Playgroud)

正如您所看到fortuneDTOs.Comments.Fortuneteller的那样不正确,因为Comments是一个集合,并且它没有名为'FullName'的属性.

您应该使用Any/All来过滤集合.例如,如果你试图找到其中一个评论员是"某些字符串"的所有命运,你就可以做到

/api/values?$top=50&$filter=Comments/any(c: c/Fortuneteller/FullName eq 'some string')
Run Code Online (Sandbox Code Playgroud)

如果你只想找到所有评论只有一个评论员"一些字符串"的所有命运,你可以做

/api/values?$top=50&$filter=Comments/all(c: c/Fortuneteller/FullName eq 'some string')
Run Code Online (Sandbox Code Playgroud)