如何根据实体输入参数过滤 IEnumerable [英] How to filter IEnumerable based on an entity input parameter

查看:19
本文介绍了如何根据实体输入参数过滤 IEnumerable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我现在正在使用实体框架 - 但这是所有 ORM 甚至 IEnumerable 之间共享"的问题.

I'm using now Entity framework- but it's a problem "shared" between all ORM's and even IEnumerable.

假设我在 MVC 中有一个方法如下所示:

Let's say I have a method in MVC looks like this:

[HttpPost]
public ActionResult Foo(FooModel model)
{
    var context = new Context(); -- The EF session
    var data = context.Foo.Where(???).ToList();
    return View(data);
}

我想根据输入参数查询上下文,例如:

I want to query the context based on the input parameter like:

var data = context.Foo.Where(x => x.Date == model.Date &&
                             x.Name == model.Name &&
                             x.ItemCode = model.ItemCode).ToList();

但它比那更复杂,因为如果上面的参数之一(Date Name ItemCode) 为空,我不'不想将它包含在查询中.
如果我硬编码,它看起来类似于:

But it's more complicated than that, because if one of the parameters above(Date Name ItemCode) is null I don't want to include it inside the query.
If I hard code it can looks similar to this:

var query =  context.Foo;

if (model.Date != null)
    query =query.Where(x => x.Date == model.Date);

if (model.ItemCode != null)
    query =query.Where(x => x.ItemCode == model.ItemCode);
...

一定有比这更简单的方法.
我需要一种方法来生成要在 Where 方法中使用的 Expression 类型的表达式.

There must be a simpler way than this.
I need a way to generate an expression of the type Expression<T, bool> to be used in the Where method.

[HttpPost]
public ActionResult Foo(FooModel model)
{
    var context = new Context(); -- The EF session
    var data = context.Foo.Where(THE_EXPRESSION).ToList();
    return View(data);
}

是否有内置的方法来构建该表达式?nuget 中是否有一个包可以做到这一点?

Is there a built-in way to build that expression? Is there a package in nuget that does it?

更新:模型实体中可能有 30 多个属性;为每个查询编写 30 次 Where 可能会让人头疼:

Update: There could be more than 30 properites in the model-entity; writing 30 times the Where for each query can be a pain in the neck:

.Where(model.Date != null, x => x.Date == model.Date)
.Where(model.Name != null, x => x.Name == model.Name)
.Where(model.ItemCode != null, x => x.ItemCode == model.ItemCode)
...
...
...
.ToList();

推荐答案

试试看.这是使用反射和表达式来动态构建查询.我只用对象测试过.

Try that. This is using reflection and expressions to build the query dynamically. I tested it only with objects.

static IQueryable<T> Filter<T>(IQueryable<T> col, T filter)
{
    foreach (var pi in typeof(T).GetProperties())
    {
        if (pi.GetValue(filter) != null)
        {
            var param = Expression.Parameter(typeof(T), "t");
            var body = Expression.Equal(
                Expression.PropertyOrField(param, pi.Name),
                Expression.PropertyOrField(Expression.Constant(filter), pi.Name));
            var lambda = Expression.Lambda<Func<T, bool>>(body, param);
            col = col.Where(lambda);
        }
    }

    return col;
}

这篇关于如何根据实体输入参数过滤 IEnumerable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆