基于空参数的Linq查询构造

Linq query construction based on empty parameters

我有一个这样的对象:

public class Filters
{
    List<string> A { get; set; }
    List<string> B { get; set; }
}

我会将其用作对数据库执行查询的函数的参数。 这些项目 A 和 B 将指示 "where" 个过滤器。

看下面的代码:

//Filters Initialization
Filters TestFilters = new Filters();
TestFilters.A = new List<string>();
TestFilters.B = new List<string>(new string[] {"testfilter1","testfilter2"}); //WHERE B == "testfilter1" OR B == "testfilter2"

//Call of the function that executes SELECT on DB
List<Table> Result = TestFunction(TestFilter);

函数:

public static List<Table> TestFunction(Filters pParameter)
{
    ExampleDataContext dc = new ExampleDataContext(Properties.Settings.Default.ExampleConnectionString);
    List<Table> SelectResult = new List<Table>();

    if (pParameter.A.count != 0 && pParameter.B.count != 0)

        SelectResult = (from x in dc.Table
            where pParameter.A.Contains(x.A)
            where pParameter.B.Contains(x.B)
            select x).ToList();

    else if (pParameter.A.count == 0 && pParameter.B.count != 0)
    {
        SelectResult = (from x in dc.Table
            where pParameter.B.Contains(x.B)
            select x).ToList();
    }

    else if (pParameter.A.count != 0 && pParameter.B.count == 0)
    {
        SelectResult = (from x in dc.Table
            where pParameter.A.Contains(x.A)
            select x).ToList();
    }

    else if (pParameter.A.count == 0 && pParameter.B.count == 0)
    {
        SelectResult = (from x in dc.Table
            select x).ToList();
    }       

    return SelectResult;
}

有时候Aor/andBis/are是空的,那我是用"IF"结构来处理的。 也许我可能会遇到这样的问题,即我的过滤器更大,参数超过 2 个,并且需要 difficult/boring 进行编码。 我的问题是:它正在工作,但是否有另一种方法可以代替使用 IF?

你可以这样做:

SelectResult = (from x in dc.Table
            where pParameter.A.Any() && pParameter.A.Contains(x.A)
            where pParameter.B.Any() && pParameter.B.Contains(x.B)
            select x).ToList();

请试一试(chained linq),我只是手工重写,没有编译或者运行:

        public static List<Table> TestFunction(Filters pParameter)
    {
        ExampleDataContext dc = new ExampleDataContext(Properties.Settings.Default.ExampleConnectionString);
        var SelectResult = dc.Table;

        if (pParameter.A.count != 0)
            SelectResult = from x in SelectResult 
                           where pParameter.A.Contains(x.A)
                           select x;

        if (pParameter.B.count != 0)
        {
            SelectResult = from x in SelectResult
                           where pParameter.B.Contains(x.B)
                           select x;
        }
        return SelectResult.ToList();
    }

代码很简单。只需使用正确的 LINQ 语法。

//Parameters class
public Class Parameters
{
    public List<string> A {get; set;}
    public List<int> B {get; set;}
}

//some function in a controller
public List<SomeResult> GetResult(Parameters pars)
{
    var db = new DbContext();
    var result = db.SomeResult.Where(s => s.Any(p =>p.SomeString == pars.A
                   || p.SomeInt == pars.B))
            .ToList();
    return result;
}

IQueryable<Table>dc.Tabledc.Table.Where() 的类型),您可以链接条件,并且仅在底行中导出 ToList。

因此,如果您将 SelectResultList<Table> 更改为 IQueryable<Table>, 每个条件都可以链接到前一个表达式,就像 AND:

public static List<Table> TestFunction(Filters pParameter)
{
    ExampleDataContext dc = new ExampleDataContext(Properties.Settings.Default.ExampleConnectionString);

    //all
    IQueryable<Table> SelectResult = dc.Table;

    //add conditions
    if (pParameter.A.count != 0 )
        SelectResult = SelectResult.Where(x => pParameter.A.Contains(x.B));
    if (pParameter.B.count != 0)
        SelectResult = SelectResult.Where(x => pParameter.A.Contains(x.B));

    //export, with one\two\zero conditions
    return SelectResult.ToList();
}

如果您的情况更复杂(例如多个条件和使用 OR 运算符),请考虑使用出色的工具 PredicateBuilder

我尝试了一些选项,但没有成功。 您可以在下面找到对我有用的代码:

List<Table> SelectResult = (from x in dc.Table
                            where (pParameter.A.Count != 0 ? pParameter.A.Contains(x.A) : true)
                            where (pParameter.B.Count != 0 ? pParameter.B.Contains(x.B) : true)
                            select s).ToList();