linq查询包含类的列表

时间:2014-01-16 21:05:40

标签: c# linq

我有一张桌子:

tblFildsVal
  - id bigint;
  - listId bigint;
  - listFieldValue bigint;
  - parrentId bigint;

然后我有一个表示4个匹配条件的数组(或List):

myArr,该
  - listId //参考listId
  - rangeType //它有4个vlaue:1)确切2)upper 3)lower 4)之间
  - 来自 //较低的值
  - //上限值

可以将多个匹配条件链接在一起,以便它对来自 tblFildsVal 的任何记录执行与任何给定条件集的匹配。

例如:

myArr{{1,1,100,Null},{2,2,125,Null},{3,3,Null,175},{4,4,125,175}}  

这意味着我想知道每个记录(由parrentId分组)中的任何一个:

(1)listId == 1 && listFieldValue == 100  
(2)listId == 2 && listFieldValue > 125  
(3)listId == 3 && listFieldValue < 175  
(4)listId == 4 && (listFieldValue > 125 && listFieldValue < 175)

(继续休息阵列)

我测试过(全部)&amp; (包含)当我有一维数组时,

var q = from flds in tblFildsVal  
        group flds by flds.parrentId into gFields  
        where myArr.All(i => gFields.Select(co => co.listFieldValue).Contains(i)) 

但在这种情况下我不知道!

1 个答案:

答案 0 :(得分:2)

您的问题是您需要实现匹配的逻辑。简单的All或Contains调用将不满足您的数组提供的匹配规则。我在下面实现了一个示例解决方案,它将显示如何编写查询以检查匹配逻辑。

class Program
{
    static void Main(string[] args)
    {
        var myMatchConditions = new int?[][]
            { 
                new int?[] { 1, 1, 100, null }, 
                new int?[] { 2, 2, 125, null }, 
                new int?[] { 3, 3, null, 175 }, 
                new int?[] { 4, 4, 125, 175 }
            };

        var myData = new MyTableItem[]
            {
                new MyTableItem { id = 1, listId = 1, listFieldValue = 150, parentId = 1 },
                new MyTableItem { id = 2, listId = 1, listFieldValue = 75, parentId = 1 },
                new MyTableItem { id = 3, listId = 2, listFieldValue = 150, parentId = 1 },
                new MyTableItem { id = 4, listId = 4, listFieldValue = 150, parentId = 1 },
                new MyTableItem { id = 5, listId = 5, listFieldValue = 150, parentId = 1 },
            };

        var matches = from d in myData
                      where myMatchConditions.Any(cond => (
                                (cond[0] == d.listId) && 
                                (cond[1] == 1 ? d.listFieldValue == cond[2] :
                                    (cond[1] == 2 ? d.listFieldValue > cond[2]  :
                                        (cond[1] == 3 ? d.listFieldValue < cond[3] :
                                            (cond[1] == 4 ? d.listFieldValue > cond[2] && d.listFieldValue < cond[3] : false)
                                        )
                                    )
                                )
                            ))
                      group d by d.parentId into g
                      select g;

    }

    class MyTableItem
    {
        public long id { get; set; }
        public long listId { get; set; }
        public long listFieldValue { get; set; }
        public long parentId { get; set; }
    }
}

需要注意的重要事项是对数组进行逻辑检查。在这里,我通过Any调用和一些嵌套的三元运算符完成了它,这不是我推荐的最终解决方案。

如果您可以为匹配条件显式创建一个类,那么可以使其更清晰,然后使用bool MatchesMe(...)之类的方法来检查每个字段,以便匹配的逻辑可以在视觉上分开来自LINQ声明。

注意:要解决使用实体框架的限制,您需要将匹配条件填充到数据库中的表中,这样您就可以将记录用作匹配逻辑中的对象;或者,更简单的是,您可以将数据库表中的结果作为IEnumerable返回,然后执行与我的示例中相同的匹配逻辑。

我建议创建一个listId参数列表,这样您只需要根据范围条件撤回需要验证的数据库记录。因此,举例来说,假设您使用List<int> myListIdFilters中的listId值设置myMatchConditions。然后,您将对逻辑检查的第一行进行更改:

var matches = from d in myData.Where(myDataItem => myListIdFilters.Contains(myDataItem.listId)).AsEnumerable()

其余的将保持不变。 AsEnumerable调用将导致IQueryable对象被解析,因此逻辑的其余部分将在EF(或LINQ to SQL)上下文之外执行。