linq 如何编写lambda表达式以从列数据中提取信息

z9ju0rcb  于 2022-12-06  发布在  其他
关注(0)|答案(2)|浏览(139)

我正在尝试从一个列中提取数据并对相同的数据应用筛选器。
如下面的屏幕截图所示,一个serviceId可以有多个userRoleId分配给它。0个或多个userRoleId作为字符串值存储在一个列userRoleIds中。当我选择一个或多个userRoleId时,我试图编写一个lambda表达式来过滤信息。

假设我将用户id 1,4,11,9作为一个列表传递,那么它应该返回以下行:

你能分享代码片段,以实现这一点,在一个单一的查询没有重复的记录。谢谢提前。
尝试用SQL UDF实现逻辑。可以实现。但需要从LINQ lambda表达式中实现。

p8h8hvxi

p8h8hvxi1#

请尝试以下操作:

int[] values = { 1, 4, 11, 9 };
            DataTable dt = new DataTable();
            dt.Columns.Add("serviceId", typeof(int));
            dt.Columns.Add("userRoleIds", typeof(int[]));

            dt.Rows.Add(new object[] { 1, new int[] { 1,5,11}});
            dt.Rows.Add(new object[] { 2, new int[] {4} });
            dt.Rows.Add(new object[] { 3, null });
            dt.Rows.Add(new object[] { 4, new int[] { 1, 4, 6, 9, 19 } });

            var results = dt.AsEnumerable().Where(x => x.Field<object>("userRoleIds") != null && x.Field<int[]>("userRoleIds").Any(y => values.Contains(y))).ToList();
bgtovc5b

bgtovc5b2#

使用LINQKit,您可以创建帮助器,允许获取分隔字符串的可能成员的List<T>,并通过为类似v == term || v.StartsWith(term + delimiter) || v.EndsWith(delimiter + term) || v.Contains(delimiter + term + delimiter)的每个术语添加 predicate ,以EF/EF Core兼容的方式搜索它。
您也可以通过滚动您自己的Expression树助手来避免LINQKit。
下面是我使用LINQKit依赖项的代码:

public static class LinqKitExt { // using LINQKit
    // string fieldExpr(T row) - function returning multiple value delimited string field to test
    // delimiter - string separator between values in test field
    // value - string value to find in splits of test field
    // r => fieldExpr(r).Split(delimiter).Contains(value)
    public static Expression<Func<T, bool>> SplitContains<T>(this Expression<Func<T, string>> fieldExpr, string delimiter, string value) {
        var pred = PredicateBuilder.New<T>(r => fieldExpr.Invoke(r) == value);
        pred = pred.Or(r => fieldExpr.Invoke(r).StartsWith(value + delimiter));
        pred = pred.Or(r => fieldExpr.Invoke(r).EndsWith(delimiter + value));
        pred = pred.Or(r => fieldExpr.Invoke(r).Contains(delimiter + value + delimiter));

        return pred;
    }

    // values - string values, one of which to find in splits of test field
    // string fieldExpr(T row) - function returning multiple value delimited string field to test
    // delimiter - string separator between values in test field
    // r => values.Any(value => fieldExpr(r).Split(delimiter).Contains(value))
    public static Expression<Func<T, bool>> SplitContainsAny<T>(this IEnumerable<string> values, Expression<Func<T, string>> fieldExpr, string delimiter) {
        var pred = PredicateBuilder.New<T>();
        foreach (var value in values)
            pred = pred.Or(fieldExpr.SplitContains(delimiter, value));

        return pred;
    }
    // values - string values, one of which to find in splits of test field
    // string fieldExpr(T row) - function returning multiple value delimited string field to test
    // delimiter - string separator between values in test field
    // dbq.Where(r => values.Any(value => fieldExpr(r).Split(delimiter).Contains(value)))
    public static IQueryable<T> WhereSplitContainsAny<T>(this IQueryable<T> dbq, Expression<Func<T, string>> fieldExpr, string delimiter, IEnumerable<string> values) =>
        dbq.AsExpandable().Where(values.SplitContainsAny(fieldExpr, delimiter));
}

有了它,您可以执行以下操作:

var ans = src.WhereSplitContainsAny(s => s.userRoleIds.Substring(1, s.userRoleIds.Length-2),
                                    ",",
                                    filter.Select(n => n.ToString()))
             .ToList();

相关问题