简体   繁体   English

带有可选 WHERE 选项的 Linq

[英]Linq with optional WHERE options

I have a .Net function that accepts 3 parameters, all optional.我有一个 .Net 函数,它接受 3 个参数,都是可选的。 Something like this:像这样的东西:

public List<MyObject> Search(string colour, string size, string name)
{
     var result = (from c in MyTable where .... select c).ToList();     
}

My question is, what is the best way to do the where part.我的问题是,执行where部分的最佳方法是什么。 Would the best be to create dynamic linq?最好的方法是创建动态 linq 吗? What's the best pattern, within linq, to have optional where parameters?在 linq 中,具有可选 where 参数的最佳模式是什么?

So, in SQL, something like this:所以,在 SQL 中,是这样的:

SELECT *
FROM MyTable
WHERE (@colour <> '' AND colour = @colour)
  AND (@size <> '' AND size = @size)
  AND (@name <> '' AND name = @name)

But I am hoping there a neater, more acceptable pattern for doing this within linq.但我希望在 linq 中有一个更简洁、更可接受的模式来执行此操作。

In such cases, I would advise you to use the PredicateBuilder to generate your queries.在这种情况下,我建议您使用PredicateBuilder来生成您的查询。 You can copy the code from here or you could install the LinqKit Nuget Package.您可以从此处复制代码,也可以安装 LinqKit Nuget 包。

Using this code will allow you to generate dynamic queries on the fly and will prevent you from writing tons of if/else statements.使用此代码将允许您即时生成动态查询,并防止您编写大量 if/else 语句。

Statements like...诸如此类的声明...

p => p.Price > 100 &&
 p.Price < 1000 &&
 (p.Description.Contains ("foo") || p.Description.Contains ("far"))

will be generated by this kind of code:将由这种代码生成:

var inner = PredicateBuilder.False<Product>();
inner = inner.Or (p => p.Description.Contains ("foo"));
inner = inner.Or (p => p.Description.Contains ("far"));

var outer = PredicateBuilder.True<Product>();
outer = outer.And (p => p.Price > 100);
outer = outer.And (p => p.Price < 1000);
outer = outer.And (inner);

I think this is fairly neat and it will also give you an understanding on how powerful expressions can be.我认为这是相当简洁的,它也会让您了解表达式的强大功能。

Chain Where clauses with checking for null带有检查空值的链式Where子句

var result = context.MyTable
    .Where(t => color == null || color == t.Color)
    .Where(t => size == null || size == t.Size)
    .Where(t => name == null || name == t.Name)
    .ToList();

Alternative approach would be to add conditions only when you need them替代方法是仅在需要时添加条件

var query = context.MyTable;

if (color != null) query = query.Where(t => t.Color == color);
if (size != null) query = query.Where(t => t.Size == size);
if (name != null) query = query.Where(t => t.Name == name);

var result = query.ToList();
var results = olstOfObjects.Where(x => 
    (x.size == size || x.size == "") &&
    (x.color == color || x.color == "") &&
    (x.name == name || x.name == "")).ToList();;

You can do something like the following in your Search method:您可以在Search方法中执行以下操作:

var query = from c in MyTable select c;
if (!String.IsNullOrEmpty(colour))
  query = from c in query where c.colour == colour select c;
if (!String.IsNullOrEmpty(size))
  query = from c in query where c.size == size select c;
if (!String.IsNullOrEmpty(name))
  query = from c in query where c.name == name select c;
return query.ToList();

How about:怎么样:

public List<MyObject> Search(string colour, string size, string name)
{
    IEnumerable<MyObject> result = MyTable;

    if(colour != null)
        result = result.Where(o => o.Colour == colour);

    if(size != null)
        result = result.Where(o => o.Size == size);

    ...

    return result.ToList();
}

Here you have 1 query with all conditions:在这里,您有 1 个具有所有条件的查询:

public List<object> Search(string colour, string size, string name)
{
    var query = from c in MyTable
        where
            (string.IsNullOrEmpty(colour) || c.colour == colour) &&
            (string.IsNullOrEmpty(size) || c.size == size) &&
            (string.IsNullOrEmpty(name) || c.name == name)
        select c;

    return query.ToList();
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM