用于链接查询组合的Linq语法

时间:2017-11-25 17:39:29

标签: c# linq

我有一些情况,我有选择的组合,需要根据选择的内容过滤数据(在这种情况下使用EF)。是否有更清晰的方式来编写以下内容而不是列出所有组合?

我的初步尝试似乎过于复杂,特别是如果组合变得更大。

DateTime today = DateTime.Now.Date;
DateTime yesterday = today.AddDays(-1);
DateTime tomorrow = today.AddDays(1);

var query = db.Products.AsQueryable();
if (userSettings.DisplayYesterday && userSettings.DisplayToday && userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday || DbFunctions.TruncateTime(x.ListedTime) == today || DbFunctions.TruncateTime(x.ListedTime) == tomorrow);
}
else if (!userSettings.DisplayYesterday && userSettings.DisplayToday && userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == today || DbFunctions.TruncateTime(x.ListedTime) == tomorrow);
}
else if (userSettings.DisplayYesterday && !userSettings.DisplayToday && userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday || DbFunctions.TruncateTime(x.ListedTime) == tomorrow);
}
else if (userSettings.DisplayYesterday && userSettings.DisplayToday && !userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday || DbFunctions.TruncateTime(x.ListedTime) == today);
}
else if (!userSettings.DisplayYesterday && !userSettings.DisplayToday && userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == tomorrow);
}
else if (!userSettings.DisplayYesterday && userSettings.DisplayToday && !userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == today);
}
else if (userSettings.DisplayYesterday && !userSettings.DisplayToday && !userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday);
}
else if (userSettings.DisplayYesterday && !userSettings.DisplayToday && !userSettings.DisplayTomorrow)
{
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday);
}
else if (!userSettings.DisplayYesterday && !userSettings.DisplayToday && !userSettings.DisplayTomorrow)
{
    //  If nothing is selected then default to today
    query = query.Where(x => DbFunctions.TruncateTime(x.ListedTime) == today);
}

List<Products> productList = await query.ToListAsync();

2 个答案:

答案 0 :(得分:3)

是的,您可以安装LinqKit nuget包并使用其PredicateBuilder(如果出于任何原因您不能\不想安装第三方包 - 您可以自己实现类似的功能)。使用PredicateBuilder,你可以这样做:

// start with false, because building OR expression
// and false OR something is the same as just something
var condition = PredicateBuilder.New<Product>(false);
if (userSettings.DisplayYesterday)
    condition = condition.Or(x => DbFunctions.TruncateTime(x.ListedTime) == yesterday);
if (userSettings.DisplayToday)
    condition = condition.Or(x => DbFunctions.TruncateTime(x.ListedTime) == today);
if (userSettings.DisplayTomorrow)
    condition = condition.Or(x => DbFunctions.TruncateTime(x.ListedTime) == tomorrow);
query = query.Where(condition);

如果您使用AND加入多个条件(而不是像此处那样的OR),则不需要谓词构建器,只需链Where调用:

if (someCondition)
    query = query.Where(x => x.SomeField == someValue);
if (anotherCondition)
    query = query.Where(x => x.SomeAnotherField == someAnotherValue);

答案 1 :(得分:1)

在Linq2Sql中你可以写

bool dispYesterday = userSettings.DisplayYesterday;
bool dispTomorrow = userSettings.DisplayTomorrow;
bool dispToday = userSettings.DisplayToday || !dispYesterday && !dispTomorrow;

query = query.Where(x =>
    dispYesterday && x.ListedTime.Date == yesterday
 || dispToday && x.ListedTime.Date == today
 || dispTomorrow && x.ListedTime.Date == tomorrow
);

它仅生成使用的条件,从而进行有效的查询。在EF中你可以写一些类似的东西,生成的sql查询会很尴尬和低效,但这是这个框架生成的大部分代码,所以没什么大不了的。