【问题标题】:How to Search through all fields in a LINQ table?如何搜索 LINQ 表中的所有字段?
【发布时间】:2013-07-30 16:15:44
【问题描述】:

在 LINQ 中如何搜索表中的所有字段,下面的 ANYFIELD 是什么?

谢谢

var tblequipments = from d in db.tblEquipments.Include(t => t.User).Include(t => t.ChangeLog).Include(t => t.AssetType)
                                where d."ANYFIELD" == "VALUE" select d;

【问题讨论】:

    标签: linq entity-framework


    【解决方案1】:

    你不能。您必须单独比较每个字段。比较所有字段没有意义,因为一个字段甚至可能与您要比较的对象的类型不同。

    【讨论】:

    • 当然不是通过 LINQ,而且应该是这样。
    • 您无法就任何事情应该如何做出陈述,因为您无法了解每个应用程序都可以从中受益。如果表格都是一种类型并且您想搜索每个字段怎么办?我可以设想几种情况,这将是有益的。实际上,这就是我找到这篇文章的原因;我想做的正是最初的要求。对于我的用户来说,用户无需单击任何其他按钮即可在框中键入任何他们想要的内容并拉出记录,这对用户来说更加友好。简单:输入任何相关信息并点击搜索。谷歌?
    • 但这不是 LINQ 的用途。这就是诀窍:想做某事是好的,但通过一个不打算以这种方式使用的工具来做是不好的。在这种情况下,也许需要改变模型。应该使用组件模式或简单的聚合/委托将属性视为它们自己的对象。
    【解决方案2】:

    你可以,使用反射。试试这个:

        static bool CheckAllFields<TInput, TValue>(TInput input, TValue value, bool alsoCheckProperties)
        {
            Type t = typeof(TInput);
            foreach (FieldInfo info in t.GetFields().Where(x => x.FieldType == typeof(TValue)))
            {
                if (!info.GetValue(input).Equals(value))
                {
                    return false;
                }
            }
            if (alsoCheckProperties)
            {
                foreach (PropertyInfo info in t.GetProperties().Where(x => x.PropertyType == typeof(TValue)))
                {
                    if (!info.GetValue(input, null).Equals(value))
                    {
                        return false;
                    }
                }
            }
            return true;
        }
    

    还有你的 LINQ 查询:

    var tblequipments = 来自 db.tblEquipments.Include(t => t.User).Include(t => t.ChangeLog).Include(t => t.AssetType) 中的 d 其中 CheckAllFields(d, "VALUE", true) 选择 d;

    如果您想检查所有字段所有属性,第三个参数应该是true,如果您只想检查所有字段,则应该是false

    【讨论】:

    • 正要发布类似的回复,但在 IQueryable 上。这将与标记为的 LINQ-to-Objects 一起使用,但我认为它在他的实际场景中不起作用,因为他使用 db.tblEquipments,这意味着他正在使用 EF 或 Linq-2-SQL。跨度>
    • @Ocelot20:也许我的解决方案行不通,但 OP 可以随时尝试。
    • 我正在使用实体框架,我是否错误地标记了这个?对不起!这个功能会起作用吗?我试过使用它,但在alsocheckproperties 语句中,我得到“方法'GetValue'没有重载需要1个参数谢谢
    • @AlexW:你有没有在代码文件的顶部添加using System.Reflection;
    • @AlexW:不幸的是,没有。如您所见in this answer,无法使用自定义方法,因为 LINQ to Entities 需要能够将表​​达式转换为 SQL。
    【解决方案3】:

    编辑:有人已经建造了这个...见here

    不是一个完整的答案,但我不同意你只是不能...

    您可以提出一个扩展方法,该方法根据您的类似类型的属性动态过滤 IQueryable/IEnumerable(我猜是 db 变量的 IQueryable)。这是在 Linqpad 中掀起的一些事情。它引用了 PredicateBuilder 并且绝不是完整/完全准确的,但我在我的一些表上使用 Linq-to-SQL 对其进行了测试,并且它按描述工作。

    void Main()
    {
        YourDbSet.WhereAllPropertiesOfSimilarTypeAreEqual("A String")
             .Count()
             .Dump();
    }
    
    public static class EntityHelperMethods
    {
        public static IQueryable<TEntity> WhereAllPropertiesOfSimilarTypeAreEqual<TEntity, TProperty>(this IQueryable<TEntity> query, TProperty value)
        {
            var param = Expression.Parameter(typeof(TEntity));
    
            var predicate = PredicateBuilder.True<TEntity>();
    
            foreach (var fieldName in GetEntityFieldsToCompareTo<TEntity, TProperty>())
            {
                var predicateToAdd = Expression.Lambda<Func<TEntity, bool>>(
                    Expression.Equal(
                        Expression.PropertyOrField(param, fieldName),
                        Expression.Constant(value)), param);
    
                predicate = predicate.And(predicateToAdd);
            }
    
            return query.Where(predicate);
        }
    
        // TODO: You'll need to find out what fields are actually ones you would want to compare on.
        //       This might involve stripping out properties marked with [NotMapped] attributes, for
        //       for example.
        private static IEnumerable<string> GetEntityFieldsToCompareTo<TEntity, TProperty>()
        {
            Type entityType = typeof(TEntity);
            Type propertyType = typeof(TProperty);
    
            var fields = entityType.GetFields()
                                .Where (f => f.FieldType == propertyType)
                                .Select (f => f.Name);
    
            var properties = entityType.GetProperties()
                                    .Where (p => p.PropertyType == propertyType)
                                    .Select (p => p.Name);
    
            return fields.Concat(properties);
        }
    }
    

    未解决部分的有用资源:

    【讨论】:

    • 抱歉,刚刚重新阅读并注意到它是“任何字段”,而不是“所有字段”。幸运的是,这只是使用predicate.Or 而不是predicate.And
    【解决方案4】:

    如果这对某人有帮助。

    首先查找 Customer 类中与查询类型相同的所有属性:

    var stringProperties = typeof(Customer).GetProperties().Where(prop =>
        prop.PropertyType == query.GetType());
    

    然后从上下文中找到所有至少有一个属性值等于查询的客户:

    context.Customer.Where(customer => 
        stringProperties.Any(prop =>
            prop.GetValue(customer, null) == query));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-07
      • 1970-01-01
      • 2021-05-31
      • 1970-01-01
      相关资源
      最近更新 更多