У меня есть модель с именем Блог:
public class Blog
{
[Key]
public int blogId { get; set; }
[Required]
public string blogTitle { get; set; }
public string imagePath { get; set; }
[Required, DataType(DataType.Html)]
public string blogDescription { get; set; }
[DataType(DataType.DateTime)]
public DateTime blogDateTime { get; set; }
[Required]
public bool isPublished { get; set; }
[Required]
public BlogCategory blogCategory { get; set; }
public List<Comments> blogComments { get; set; }
}
И еще модель Комментарий:
public class Comments
{
[Key]
public int authorId { get; set; }
[Required]
public string commentAuthor { get; set; }
[DataType(DataType.Date)]
public DateTime commentDate { get; set; }
public bool isHidden { get; set; }
[Required, DataType(DataType.EmailAddress)]
public string commentAuthorEmail { get; set; }
[Required]
public string commentDescription { get; set; }
public Blog Blog { get; set; }
}
В контроллере блогов я хочу получить доступ ко всем комментариям, где isHidden = false
Что я пробовал:
var blog = await _context.Blog
.Include(cat => cat.blogCategory)
.Include(comments => comments.blogComments.Any(c => !c.isHidden))
.FirstOrDefaultAsync(m => m.blogId == id);
Но все, что я получаю, это исключение
An unhandled exception occurred while processing the request.
InvalidOperationException: The Include property lambda expression 'comments => comments.blogComments.Find(c => Not(c.isHidden))' is invalid. The expression should represent a property access: 't => t.MyProperty'. To target navigations declared on derived types, specify an explicitly typed lambda parameter of the target type, E.g. '(Derived d) => d.MyProperty'.
Как я могу решить эту проблему?
Возможный дубликат EF: включить в предложение where
@GertArnold Я не думаю, что это возможный дубликат. Я хотел бы попросить вас рассмотреть этот вопрос еще раз. Если можно, помогите пожалуйста.
Не дубликат? Что еще вы спрашиваете, кроме как сделать отфильтрованное включение?
логическое значение истинно или ложно, поэтому попробуйте: // не проверено
(comments => comments.blogComments.where(c=>c.isHidden==false))
var blog = await _context.Blog
.Include(cat => cat.blogCategory)
.Include(comments => comments.blogComments)
.Select(x=> {
x.blogCategory = x.blogCategory;
x.blogComments = x.blogComments.Where(y=>!y.IsHidden)
})
.FirstOrDefaultAsync(m => m.blogId == id);
Поскольку это IQueryable, это будет иметь тот же результат. Он вернет только те комментарии, где комментарии блога скрыты. Это при условии, что вы хотите вернуть все блоги, а не только блоги, чьи комментарии скрыты.
Однако это не возвращает Blog
.
Хитрость здесь заключается в операторе select. С ним вы можете вернуть все, что захотите. Например, новый блог(){ mpla mpla}
Вы не могли сделать фильтр в Include
в ядре EF, вместо этого попробуйте использовать приведенный ниже код.
var blog = await _context.Blog
.Include(cat => cat.blogCategory)
.Include(comments => comments.blogComments)
.FirstOrDefaultAsync(m => m.blogId == id);
blog.blogComments = blog.blogComments.Where(b => b.isHidden == false).ToList();
Вы должны использовать проекции структуры сущностей.
var blog = await _context.Blog
.Select(p => new Blog
{
blogComments = p.blogComments.Where(s => !s.isHidden )
}.FirstOrDefaultAsync(m => m.blogId == id);
"должен" - это сильно сказано
афаик другого выхода нет. посмотрите пожалуйста. stackoverflow.com/questions/43618096/…
К сожалению, фильтрация при использовании include невозможна (пока). Подробнее см. в здесь. Альтернативой является использование глобальных фильтров, но это может иметь другие последствия для вашего приложения.