C# 如何动态构造/更改LINQ语句的一部分

C# 如何动态构造/更改LINQ语句的一部分,c#,linq,C#,Linq,我的应用程序中有一个方法,需要根据一组标准读取、过滤和提供数据。 我正在尝试使用LINQ来实现这一点: var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow) where data.Stage.ToLower().Contains("won") && data.RevenueStartDate.Value.Year == DateTime

我的应用程序中有一个方法,需要根据一组标准读取、过滤和提供数据。 我正在尝试使用LINQ来实现这一点:

var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow)
         where data.Stage.ToLower().Contains("won")
         && data.RevenueStartDate.Value.Year == DateTime.Today.Year
         && data.WeekOfTheYear >= priorWeekCutoff
         && (!string.IsNullOrEmpty(data.PlatformTcv) && data.PlatformTcv != "#N/A")
         select data; 
就其本身而言,这一切都很好。问题是-根据正在传递的搜索条件,可能是data.WorkspaceTvc或data.CyberTvc,而不是data.PlatformTvc。。。 我没有办法提前知道5个可能的选择中哪一个需要评估

我的问题是:有没有一种方法可以以这样的方式构造LINQ语句,即语句的一部分是有条件执行的。因此,如果用户通过平台作为搜索条件,LINQ语句将读取。。。string.IsNullOrEmptydata.PlatformTcv,但如果条件是Cyber,则此LINQ语句应为。。。string.IsNullOrEmptydata.CyberTcv
有办法做到这一点吗?

当然。利用LINQs延迟执行模型,在查询中嵌入可变谓词。例如:

Func<DataObject, string> accessor = data => data.PlatformTcv;

var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow)
                   where data.Stage.ToLower().Contains("won")
                       && data.RevenueStartDate.Value.Year == DateTime.Today.Year
                       && data.WeekOfTheYear >= priorWeekCutoff
                       && (!string.IsNullOrEmpty(accessor(data))
                       && accessor(data) != "#N/A")
                   select data;

var basedOnPlatform = pipelineData.ToArray();

accessor = data => data.CyberTV;

var basedOnCyber = pipelineData.ToArray();
这假定查询元素类型为DataObject。当然,您可以将其替换为您正在使用的任何类型的实际名称


请记住,这将使LINQ更难理解,并始终记住查询的延迟执行性质。也就是说,如果它们没有具体化为其他集合,例如调用ToArray,那么在下次执行时,将显示对基础查询的更改。

您可以为零件创建一个IQueryable,该IQueryable与所有查询相同:

var pipelineData = from data in new XPQuery<AccountView3.PipelineData>(uow)
     where data.Stage.ToLower().Contains("won");
     // etc

仔细的OP可能希望重用我在文章中不完全清楚的原始查询,因此您可能不希望将新的筛选版本分配回原始变量。值得注意的是,至少对于最初的示例,这个解决方案可能比我提供的方法更可读、更易于维护。它不能推广到LINQ查询的其他元素,但是如果你只是做过滤,这是一个非常好的选择。这真是天才!非常感谢。
if (somecondition) 
{
    pipelineData = pipelineData.Where(x => x.SomeField == "somevalue");
}
// etc