#c# #asp.net-mvc #entity-framework
#c# #asp.net-mvc #entity-framework
Вопрос:
Мне нужно написать какое-то выражение динамического выбора в entity Framework, что-то вроде приведенного в примере.
var list = db.Article
.GroupBy(x => x.CategoryId)
.Select(x => new ArtDto
{
No = x.Select(c => c.NUMBER).FirstOrDefault(),
UserName = x.Key,
Count = x.Count()
})
.ToList();
Я могу написать group by с таким выражением:
Expression<Func<Article, int>> groupByExp;
groupByExp = (x) => x.CategoryId;
Таким образом, я могу заменить фактическое выражение на groupByExp.
var list = db.Article
.GroupBy(groupByExp)
.Select(x => new ArtDto
{
No = x.Select(c => c.NUMBER).FirstOrDefault(),
UserName = x.Key,
Count = x.Count()
})
.ToList();
Я также хочу написать другое выражение для выбора. Поэтому я могу отправить его в другую функцию, и оно будет динамичным для этой функции.
Expression<Func<Article, bool>> selectExp;
selectExp = (x) => new ArtDto { ... };
Возможно ли это? У вас есть какая-нибудь идея или учебник для этого?
Комментарии:
1. Можете ли вы привести пример того, что вы хотите попробовать? Вы думали о последствиях для
var list
?2. Вы можете просто передать different
Func<IGrouping<Article>, ArtDto>
в select3. @KrzysztofSkowronek можете ли вы привести мне пример?
4. @HenkHolterman Я только что обновил свой пост. Мне нужно написать другое выражение для выбора, и я могу отправить это выражение в другую функцию. Так что оно будет динамическим.
5. Итак, какой тип должен
list
быть? Это можно заставить работать, только возвращаясьdynamic
везде.
Ответ №1:
Да, это возможно,
перед запуском вам необходимо:
- Создайте новый объект для выбранных свойств
- Сопоставьте вашу модель с новым объектом
давайте рассмотрим, что у вас есть ваша модель Article
, и вам нужно вернуть новую модель ArticleSummary
, как показано ниже
public class Article {
public int id { get; set; }
public string Title { get; set; }
public string Introduction { get; set; }
public string AuthorId { get; set; }
public AppUser Author { get; set; }
public DateTime PublishDate { get; set; }
}
public class ArticleSummary {
public int Id { get; set; }
public string Title { get; set; }
public string Introduction { get; set; }
}
и вот отображение :
Expression<Func<Article, ArticleSummary>> mapArticle = x => new ArticleSummary {
Id = x.Id,
Title = x.Title,
Introduction = x.Introduction
};
и вот «упрощенная» функция передачи данных :
// T is Article model
// U is ArticleSummary model
public async Task<ICollection<U>> SelectListAsync<T, U>(
Expression<Func<T, bool>> search,
Expression<Func<T, U>> select) where T : class
{
var query =
_context.Set<T>()
.Where(search)
.Select(select);
return await query.ToListAsync();
}
вы можете вызвать его, передав выражение сопоставления в свойство выбора.
Ответ №2:
Ваше выражение должно приниматься IIGrouping<T, Article>
в качестве первого аргумента (где T
— тип CategoryId
). Предполагая, что CategoryID является int
выражением, можно записать как
public static Expression<Func<IGrouping<int, Article>, ArtDto>> SelectExpression()
{
return x => new ArtDto
{
No = x.Select(c => c.NUMBER).FirstOrDefault(),
UserName = x.Key,
Count = x.Count()
};
}