Как написать выражение динамического выбора

#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> в select

3. @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()
    };
}