Вложенный фильтр объекта передачи данных с использованием OData Wep Api

У меня есть проект app app, который использует данные с помощью odata, но у меня возникают некоторые проблемы с odata wep api.

когда я выполняю этот запрос

/api/values? $top = 50 & $filter = Комментарии /Fortuneteller/FullName eq 'some string'

это дает мне следующую ошибку

"Сообщение": "Запрос, указанный в URI, недействителен.", "ExceptionMessage": "Родительское значение для доступа к свойствам свойства" Fortuneteller "не является единственным значением. Доступ к свойствам может применяться только к одному значению."

Я не хочу возвращать объект объекта из контроллера. Есть ли способ фильтрации объекта через DTO?

Я использую шаблон Repository + Service layer в моем проекте, и структура моего проекта похожа на

api controller ↔ service ↔ репозиторий ↔ 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 неверно, поскольку комментарии являются коллекцией и не имеют свойства с именем "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')