EF-Linq 将实体对象转换为搜索条件以进行通用动态查询

2 篇文章 0 订阅

网上找了很久都没找到想要的代码,于是自己写了一份,以作分享。

思路是根据传递进来的对象通过反射来获取对应的属性及属性值,然后再进行比较,接着返回Func对象。

方法主体:

        /// <summary>
        /// 根据传递的对象生成Func表达式,作为Linq的Where参数
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        public static Func<T, bool> GetFunc<T>(T obj)
        {
            if (obj == null) return null;
            Func<T, bool> func = item =>
            {
                Type t = typeof(T);
                foreach (var prop in t.GetProperties())
                {
                    if (!PropIsEquals(prop.PropertyType, prop.GetValue(item), prop.GetValue(obj)))//此处判断item是否符合搜索条件
                    {
                        return false;
                    }
                }
                return true;
            };
            return func;
        }

<span style="white-space:pre">	</span>/// <summary>
        /// 根据属性类型及属性值进行比较
        /// </summary>
        /// <param name="_type">属性类型</param>
        /// <param name="val1">待比较的值</param>
        /// <param name="val2">比较值</param>
        /// <returns></returns>
        public static bool PropIsEquals(Type _type, object val1, object val2)
        {
            if (val1 == null) return true;//如果属性值为空,则不进行比较,返回true

            if (val2 != null && val1 == null) return false;//如果比较值不为Null但是待比较的值为Null,则肯定不相等,返回false

            if (val2 == null && val1 != null) return true;

            //String
            if (_type == typeof(String))
            {
                if (val2.ToString() == String.Empty) return true;//视为空,不比较
                return val1.ToString().Contains(val2.ToString());//like查询,可改成Equals
            }
            else if (_type == typeof(Nullable<DateTime>))
            {
                return val1.ToString().Contains(val1.ToString());
            }

            //Int32
            if (_type == typeof(Int32))
            {
                if (Convert.ToInt32(val2) == 0) return true;//视为空,不比较
                return Convert.ToInt32(val1) == Convert.ToInt32(val2);
            }
            else if (_type == typeof(Nullable<Int32>))
            {
                return Convert.ToInt32(val1) == Convert.ToInt32(val2);
            }

            //DateTime
            if (_type == typeof(DateTime))
            {
                if (Convert.ToDateTime(val2) == DateTime.MinValue) return true;//视为空,不比较
                return Convert.ToDateTime(val1) == Convert.ToDateTime(val2);
            }
            else if (_type == typeof(Nullable<DateTime>))
            {
                return Convert.ToDateTime(val1) == Convert.ToDateTime(val2);
            }

            //Boolean
            if (_type == typeof(Boolean))
            {
                if (Convert.ToBoolean(val2) == false) return true;//视为空,不比较
                return Convert.ToBoolean(val1) == Convert.ToBoolean(val2);
            }
            else if (_type == typeof(Nullable<DateTime>))
            {
                return Convert.ToBoolean(val1) == Convert.ToBoolean(val2);
            }

            //Boolean
            if (_type == typeof(Guid))
            {
                if (Guid.Parse(val2.ToString()) == Guid.Empty) return true;//视为空,不比较
                return Guid.Parse(val1.ToString()) == Guid.Parse(val2.ToString());
            }
            else if (_type == typeof(Nullable<Guid>))
            {
                return Guid.Parse(val1.ToString()) == Guid.Parse(val2.ToString());
            }

            return true;
        }
OK,以上就是全部代码,调用示例:

        var data = from item in (new VocationalEducationEntities().UserInfo) select item;//获取数据源
        var condition=new UserInfo(){Name="A",Sex="男"};//查询条件,此处手动构造
        var newData = data.Where(Common.GetFunc<UserInfo>(condition));//获取姓名等于A,性别等于男的用户


相信很多人看完之后就知道这个方法的缺陷:

1,每次查询都会调用反射,效率不够高效,有关反射效率讨论的文章>>点击打开链接

2,没有比较的关系并且不能进行稍稍复杂的判断,如Age>18并且Age<20,这种判断就写不了


总结:此方法有一定的通用性,但实用性还不够,不过简单使用还是可以的!

最后,希望大家看完之后能够提供一些改正的意见,谢谢!




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C# 中使用 LINQ 进行动态查询对象,可以使用 `System.Linq.Expressions` 库。这个库提供了一种将 LINQ 查询表达式表示为树形结构的方式,可以在运行时动态构建和修改这个树形结构。下面是一个示例代码: ```csharp using System.Linq.Expressions; string propertyName = "Name"; string propertyValue = "Tom"; var parameter = Expression.Parameter(typeof(MyClass), "x"); var property = Expression.Property(parameter, propertyName); var constant = Expression.Constant(propertyValue); var equal = Expression.Equal(property, constant); var lambda = Expression.Lambda<Func<MyClass, bool>>(equal, parameter); var query = list.Where(lambda); ``` 在这个示例中,我们首先定义了要查询的属性名和属性值。然后,我们使用 `Expression.Parameter` 方法创建了一个类型为 `MyClass` 的参数表达式,并命名为 `x`。接着,我们使用 `Expression.Property` 方法创建了一个属性表达式,表示要查询的属性。然后,我们使用 `Expression.Constant` 方法创建了一个常量表达式,表示属性值。接着,我们使用 `Expression.Equal` 方法创建了一个相等比较表达式,将属性表达式和常量表达式作为参数。最后,我们使用 `Expression.Lambda` 方法将比较表达式和参数表达式组合成一个 lambda 表达式,并定义了返回类型为 `bool` 的委托类型。这个 lambda 表达式表示了一个动态查询条件。我们可以将这个 lambda 表达式作为参数传递给 LINQ 查询的 `Where` 方法,即可完成动态查询。 需要注意的是,使用 `System.Linq.Expressions` 库进行动态查询时,需要熟悉 LINQ 查询表达式的语法和结构,才能正确构建和修改查询树形结构。 希望这个答案能够解决您的问题。如果您有其他问题,可以继续提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值