如何编写动态选择表达式

时间:2019-04-12 11:57:12

标签: c# asp.net-mvc 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();

我可以用这样的表达式编写分组依据:

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 { ... };

有可能吗?您有任何想法或教程吗?

2 个答案:

答案 0 :(得分:2)

是的,

开始之前,您需要:

  • 为所选属性创建新对象
  • 将模型映射到新对象

让我们认为您拥有模型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();
}

您可以通过传递映射表达式来选择属性来调用它。

答案 1 :(得分:1)

您的表达式应将IIGrouping<T, Article>作为第一个参数(其中TCategoryId的类型)。假设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()
    };
}