web-dev-qa-db-ja.com

OData WebAPIを使用したデータ転送オブジェクトのネストされたフィルター

Wep apiプロジェクトがodataを使用してデータを消費しますが、odata wepapiに問題があります。

そのクエリを実行すると

/ api/values?$ top = 50&$ filter = Comments/Fortuneteller/FullName eq '文字列'

次のエラーが発生します

"メッセージ": "URIで指定されたクエリが無効です。"、 "ExceptionMessage": "プロパティ 'Fortuneteller'のプロパティアクセスの親値が単一の値ではありません。プロパティアクセスは単一の値にのみ適用できます値。"

コントローラからエンティティオブジェクトを返したくありません。 DTOを介してエンティティをフィルタリングする方法はありますか?

プロジェクトでリポジトリ+サービスレイヤーパターンを使用していますが、プロジェクトの構造は次のようになっています。

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; }
}
18
emreturan

例外メッセージが示すように、あなたが持っているクエリは無効です。

/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を使用する必要があります。たとえば、コメンテーターの1人が「文字列」であるすべての運命を見つけようとしている場合は、次のことができます。

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

代わりに、すべてのコメントが1人のコメンテーター「文字列」だけによって行われるすべての運命を知りたい場合は、次のことができます。

/api/values?$top=50&$filter=Comments/all(c: c/Fortuneteller/FullName eq 'some string')
29