我正在尝试使用以下LINQ查询表达式实现级联控件。
我的想法是,我有两个由表OptionA,OptionB和OptionC表示的选项列表和一个名为OptionIndex的视图,每个列有一个用于OptionA_ID,OptionB_ID,OptionC_ID的列,该表包含选项列表中所有标记的组合正在使用中。左外连接选项列表上的OptionIndex会为选项标记中的Disabled属性生成一个布尔值。
如何使on子句,即以下示例代码中的.Where(...)允许使用的控件的任意组合?
例如,假设用户最初在OptionA中选择选项值123。返回OptionC的值,标签和禁用布尔值的代码如下所示:
from t1 in OptionCs
from t2 in OptionIndexes.Where(x => t1.OptionC_ID == x.OptionC_ID && new List<int> { 123 }.Contains(x.OptionA_ID)).DefaultIfEmpty()
group new {t1, t2} by new { t1.OptionC_ID, t1.Label } into g
select new { g.Key.OptionC_ID, g.Key.Label, Disabled = g.Count(t => t.t2.OptionC_ID == null) > 0 }
然后假设用户在OptionB中选择选项值456和789。返回OptionC的值,标签和禁用布尔值的代码更改为:
from t1 in OptionCs
from t2 in OptionIndexes.Where(x => t1.OptionC_ID == x.OptionC_ID && new List<int> { 123 }.Contains(x.OptionA_ID) && new List<int> { 456, 789 }.Contains(x.OptionB_ID)).DefaultIfEmpty()
group new {t1, t2} by new { t1.OptionC_ID, t1.Label } into g
select new { g.Key.OptionC_ID, g.Key.Label, Disabled = g.Count(t => t.t2.OptionC_ID == null) > 0 }
为了使示例代码更易于理解,我使用了new List<int>
。在实际项目中,我将从控件本身作为整数数组传递选项列表中的整数。
技巧以某种方式使查询表达式动态化,以便它可以表示正在使用的0到N个多选控件的任意组合,或者传递一些东西来告诉连接接受任何给定控件的任何值,例如
{x.OptionB_ID.Any}.Contains(x.OptionB_ID)
处理此问题的最佳方法是什么?
谢谢!
答案 0 :(得分:2)
将问题提炼为一个简单的例子,请考虑这个整数列表:
List<int> l = new List<int> { 1, 25, 3, 99, -23, 0, 15, 75 };
假设您要根据外部条件有条件地过滤此列表。有时您想要正数,有时您想要小于50的数字,有时您希望数字可被5整除,或者这些数字的任意组合。使用静态表达式应用所有过滤器将如下所示:
l.Where(n => n > 0).Where(n => n < 50).Where(n => n % 5 == 0);
要动态应用任何或所有这些,只需构建LINQ查询:
// These switches simulate your external conditions.
bool conditionA = true;
bool conditionB = false;
bool conditionC = true;
IEnumerable<int> myList = l;
if (conditionA) { myList = myList.Where(n => n > 0 ); }
if (conditionB) { myList = myList.Where(n => n < 50 ); }
if (conditionC) { myList = myList.Where(n => n % 5 == 0); }
在我的示例中设置了开关,输出为25,15,75。
旁注:如果您不了解,请使用LINQPad来尝试这样的事情。对于基本上以交互方式执行代码而言,它是一个很棒的工具,无论是否为LINQ代码。当我构建上面的示例时,我在最后4行的每一行之后插入myList.Dump();
次调用,这样我就可以看到每个过滤器的应用方式。这是输出: