VB.net中,如何动态构建Linq的Where子句

望諸公 2020-03-26 10:13:12
加精
做一个通用程序,由于关键字和值都不确定,怎样写出完整的Linq语句?
请使用VB.Net、Linq来回答,谢谢各位!请尽快!
...全文
9966 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
qq_51250209 2020-09-30
  • 打赏
  • 举报
回复
我想问一下,我在网上找了一个程序,是用c语言弄出心形图形。我的程序与它的程序一模一样,可是为什么我运行出来的心形图形不完整啊?
望諸公 2020-05-28
  • 打赏
  • 举报
回复
VB.NET里面,Linq可以在VS内部组织数据,并非一定要用Linq访问数据库来跟SQL比较,暂时没发现Linq以外的有类似功效的方法,所以从这个方向来解决问题是没错的。
各位的提点,我要深入些了解再回贴
圣殿骑士18 2020-05-26
  • 打赏
  • 举报
回复
引用 8 楼 望諸公 的回复:
回答一下2楼的说法,是这样的,在VS里面处理了一些行集,这些行集在不同的DataTable,并且无法事先用RowFilter把它们找出来,需要在过程中把多个表通过 例如主键比较,从而关联起来,所以Where子句没法直接确定用哪个字段关联。 3楼的方法,我再研究一下,暂时还不是很明解,如果能稍微再解释下原理就好了,原谅我是个初手! 至于6楼,不管你会不会,或说不说,对大家都没什么意义,你说是吧。
6楼的话,当然有意义了,只是你不懂而已。我非常同意他说的,你既然无法确定关键字,那要linq干嘛?应该直接写sql是最好的。用linq性能还差,因为构造表达式树需要时间啊,你这操作类似于把sql字符串转成linq,然后送到数据库前由linq转成字符串,这是在干嘛?裤子拉上了又退下,一点用处也没。
jhonsonzhang 2020-05-23
  • 打赏
  • 举报
回复
我一直是顶老马的,但今天这个,老马唐突了,楼主应该是在模糊搜索键值上遇到瓶颈了,需要用到反射,而不是具体实体。
跳动de指尖 2020-05-15
  • 打赏
  • 举报
回复
我曾经写过一个 ,在ViewModel上标注特性,然后使用Entity属性生成lambda表达式的方法 不过是C#的,不太完善,当抛砖引玉吧

    public static class ExpressAction
    {
        internal class QueryField
        {
            public ViewModelLabelAttribute Label { get; set; }

            public PropertyInfo Property { get; set; }

            public object Value { get; set; }

            internal Expression HandleField(ParameterExpression parameter)
            {
                if (Value == null) return Expression.Empty();
                var memberExpr = Expression.Property(parameter, Property);
                switch (Label.Comparison)
                {
                    case ExpressComparison.Equal:
                        return Expression.Equal(memberExpr, Expression.Constant(Value));
                    case ExpressComparison.Gt:
                        return Expression.GreaterThan(memberExpr, Expression.Constant(Value));
                    case ExpressComparison.GtOrEqual:
                        return Expression.GreaterThanOrEqual(memberExpr, Expression.Constant(Value));
                    case ExpressComparison.Lt:
                        return Expression.LessThan(memberExpr, Expression.Constant(Value));
                    case ExpressComparison.LtOrEqual:
                        return Expression.LessThanOrEqual(memberExpr, Expression.Constant(Value));
                    case ExpressComparison.NoEqual:
                        return Expression.NotEqual(memberExpr, Expression.Constant(Value));
                    case ExpressComparison.Contains:
                        if (Property.PropertyType == typeof(string) && Value is string)
                        {
                            var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) });
                            if (containsMethod != null)
                            {
                                return Expression.Call(memberExpr, containsMethod,
                                    Expression.Constant(Property.GetValue(null)), Expression.Constant(Value));
                            }
                        }

                        if (typeof(IEnumerable).IsAssignableFrom(Property.PropertyType))
                        {
                            var containsMethod = typeof(Enumerable)
                                .GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
                                .FirstOrDefault(x =>
                                    x.Name == "Contains" && x.ReturnType == typeof(bool) &&
                                    x.GetParameters().Length == 2);

                            if (containsMethod != null)
                            {
                                containsMethod = containsMethod.MakeGenericMethod(Value.GetType());
                                return Expression.Call(containsMethod,  memberExpr,Expression.Constant(Value));
                            }
                        }
                        throw new NotImplementedException("string、IEnumerable以外类型的Contains表达式未实现!");
                    case ExpressComparison.Custom:
                        throw new NotImplementedException("暂无自定义实现");
                }

                return Expression.Empty();
            }



        }

        public static Expression<Func<TEntity, bool>> GenerateExpressTree<TEntity>(this IMapFrom<TEntity> mapFrom) where TEntity : IBaseEntity, new()
        {
            var parameter = Expression.Parameter(typeof(TEntity), "__q");

            var queryFieldsExpression = (from x in mapFrom.GetType().GetProperties()
                                         let attr = x.GetCustomAttribute<ViewModelLabelAttribute>()
                                         where attr != null
                                         let field = new QueryField
                                         {
                                             Label = attr,
                                             Property = typeof(TEntity).GetProperty(x.Name),
                                             Value = x.GetValue(mapFrom)
                                         }
                                         select field.HandleField(parameter)).Where(x => x.NodeType != ExpressionType.Default).ToList();

            var expression = (Expression)Expression.Constant(true);//(Expression)Expression.Equal(Expression.Constant(1), Expression.Constant(1));
            foreach (var expr in queryFieldsExpression)
            {
                if (queryFieldsExpression.IndexOf(expr) == 0)
                {
                    expression = expr;
                    continue;
                }
                expression = Expression.AndAlso(expression, expr);
            }
            return Expression.Lambda<Func<TEntity, bool>>(expression, parameter);
        }
    }

//枚举
    public enum ExpressComparison
    {
        /// <summary>
        /// 等于
        /// </summary>
        Equal,
        /// <summary>
        /// 包含
        /// </summary>
        Contains,
        /// <summary>
        /// 不等于
        /// </summary>
        NoEqual,
        /// <summary>
        /// 大于
        /// </summary>
        Gt,
        /// <summary>
        /// 小于
        /// </summary>
        Lt,
        /// <summary>
        /// 大于或等于
        /// </summary>
        GtOrEqual,
        /// <summary>
        /// 小于或等于
        /// </summary>
        LtOrEqual,

        /// <summary>
        /// 自定义规则
        /// </summary>
        Custom
    }

//自定义特性
    [AttributeUsage(AttributeTargets.Property)]
    public class ViewModelLabelAttribute:Attribute
    {
        public ExpressComparison Comparison { get; private set; }

        /// <summary>
        /// 生成表达式树,需要比较的方式
        /// </summary>
        /// <param name="expressComparison">比较方式</param>
        public ViewModelLabelAttribute(ExpressComparison expressComparison)
        {
            Comparison = expressComparison;
        }
    }

//测试

        internal class VmTest : IMapFrom<TestCollection>
        {
            [ViewModelLabel(ExpressComparison.Contains)]
            public string Tags { get; set; }

            public string Name { get; set; }

            public int Age { get; set; }
        }

        [TestMethod]
        public async Task UseViewModelQuery()
        {
            var vm = new VmTest{Tags = "Tag99"};
            var expr = vm.GenerateExpressTree();
            var exprResult = RepositoryUnitTest.CreateRepository<TestCollection>().SearchFor(expr);
            var list = await exprResult.ToListAsync();
            Assert.IsTrue(list.Count >= 0);
        }
望諸公 2020-05-12
  • 打赏
  • 举报
回复
回答一下2楼的说法,是这样的,在VS里面处理了一些行集,这些行集在不同的DataTable,并且无法事先用RowFilter把它们找出来,需要在过程中把多个表通过 例如主键比较,从而关联起来,所以Where子句没法直接确定用哪个字段关联。
3楼的方法,我再研究一下,暂时还不是很明解,如果能稍微再解释下原理就好了,原谅我是个初手!
至于6楼,不管你会不会,或说不说,对大家都没什么意义,你说是吧。
初学者liwd 2020-05-05
  • 打赏
  • 举报
回复
谢谢哈,我去试一下
  • 打赏
  • 举报
回复
逻辑良好、能在编程开发时就立刻看出错误的、并且有者基本的性能优势的方式,起码是你写的代码立刻经过词法分析让机器可以感知到你写了什么“关键字”。如果你连关键字都写不出来,何必开始写Linq语句呢?
别闹官人丶 2020-05-04
  • 打赏
  • 举报
回复
这个一看就是大神,牛逼。。。。
threenewbee 2020-03-30
  • 打赏
  • 举报
回复
如果是linq to sql/ef,可以用下面的
Imports System.Linq.Expressions
Imports System.Linq
Imports System.Collections.Generic

Class A
Public Property Name As String
Public Property ID As Integer
Public Overrides Function ToString() As String
Return ID & "," & Name
End Function
End Class

Module Module1

Function MyWhere(Of T)(ByVal data As IQueryable(Of T), ByVal propname As String, ByVal value As Object) As IQueryable(Of T)
Dim param = Expression.Parameter(GetType(T), "x")
Dim body = Expression.Equal(Expression.MakeMemberAccess(param, GetType(T).GetProperty(propname)), Expression.Constant(value))
Dim lambdaexpr As Object = Expression.Lambda(body, param)
Return data.Where(CType(lambdaexpr, Expression(Of Func(Of T, Boolean))))
End Function

Sub Main()
Dim list As New List(Of A)
list.Add(New A() With {.ID = 1, .Name = "a"})
list.Add(New A() With {.ID = 2, .Name = "b"})
list.Add(New A() With {.ID = 3, .Name = "c"})
Console.WriteLine(MyWhere(list.AsQueryable(), "Name", "a").First())
Console.WriteLine(MyWhere(list.AsQueryable(), "ID", 2).First())
End Sub

End Module
threenewbee 2020-03-30
  • 打赏
  • 举报
回复
https://download.csdn.net/download/caozhy/12285485
Imports System.Linq.Expressions
Imports System.Linq
Imports System.Collections.Generic

Class A
Public Property Name As String
Public Property ID As Integer
Public Overrides Function ToString() As String
Return ID & "," & Name
End Function
End Class

Module Module1

Function MyWhere(Of T)(ByVal data As IEnumerable(Of T), ByVal propname As String, ByVal value As Object) As IEnumerable(Of T)
Dim param = Expression.Parameter(GetType(T), "x")
Dim body = Expression.Equal(Expression.MakeMemberAccess(param, GetType(T).GetProperty(propname)), Expression.Constant(value))
Dim lambdaexpr As Object = Expression.Lambda(body, param).Compile()
Return data.Where(CType(lambdaexpr, Func(Of T, Boolean)))
End Function

Sub Main()
Dim list As New List(Of A)
list.Add(New A() With {.ID = 1, .Name = "a"})
list.Add(New A() With {.ID = 2, .Name = "b"})
list.Add(New A() With {.ID = 3, .Name = "c"})
Console.WriteLine(MyWhere(list, "Name", "a").First())
Console.WriteLine(MyWhere(list, "ID", 2).First())
End Sub

End Module
hztltgg 2020-03-30
  • 打赏
  • 举报
回复
linq方便编程时强类型的代码提示,如果都是动态的,那和拼接sql语句好像就没什么区别了,如果是为了返回实体对象,用SqlQuery方法也可以直接写sql返回实体,和上面的 Dynamic Linq 也没什么大区别
q107770540 2020-03-30
  • 打赏
  • 举报
回复
Try Dynamic Linq: https://weblogs.asp.net/scottgu/dynamic-linq-part-1-using-the-linq-dynamic-query-library

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧