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; }
}
例外メッセージが示すように、あなたが持っているクエリは無効です。
/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')