首页 文章

LINQ,使用动态字段名称获取字符串列表

提问于
浏览
0

所以我想从表中返回一个唯一值类型的String列表 .

值得注意的是,该表的设计者决定表中的每一行都有多个具有多个唯一字段的列 . 因此,您不仅可以从表中获取指定字段所需的唯一项目列表,然后获得区别 .

所以为此,我想编写一个通用方法,我可以在其中指定列名并获取唯一的项列表 .

我尝试了下面列出的两种方法;

retList = context.LP_Specification.Select(x => x.GetType().GetProperty(fieldName).GetValue(x).ToString()).Distinct().ToList();

retList = context.LP_Specification.Select(fieldName)

也行不通 .

但是我使用这样的反射得到错误 .

所以方法调用看起来像这样;

public List<string> GetSpecs(string fieldName)

我想从表中获取字符串值列表,只返回指定字段的不同值 .

3 回答

  • 3

    您不需要使用反射获取每个对象的属性值,因为此查询将针对数据库执行,因此该方法不起作用(除非在查询内存中的集合中) .

    您需要构建一个动态表达式树来实现您想要的 . 一个简单的例子是这样的:

    // Building expression x=> x.FieldName
    ParameterExpression foo = Expression.Parameter(typeof(Foo), "x");
    MemberExpression selection = Expression.PropertyOrField(foo, "FieldName");
    var lambdaExp = Expression.Lambda<Func<Foo, string>>(selection, foo);
    

    用法:

    retList = context.LP_Specification.Select(lambdaExp).Distinct();
    

    以上假设实体类型为 Foo ,属性名为 "FieldName" .

    您始终可以创建一个扩展方法:

    public static class MyExtensions
    {
        public static IQueryable<V> SelectByName<T, V>(this IQueryable<T> source, 
                                                            string FieldName)
        {
            ParameterExpression paramExp = Expression.Parameter(typeof(T), "x");
            MemberExpression memberExp = Expression.PropertyOrField(paramExp, FieldName);
            var lambdaExp = Expression.Lambda<Func<T, V>>(memberExp, paramExp);
    
            return source.Select(lambdaExp);
        }
    }
    

    用法:

    retList = context.LP_Specification
                     .SelectByName<LP_Specification, string>("SomeFieldName").Distinct();
    
  • 1

    我想你可以使用这样的通用方法:

    private IEnumerable<string> GetResult<T>(IEnumerable<T> list, string propName)
    {
        var retList = new List<string>();
    
        var prop = typeof (T).GetProperty(propName);
        if (prop == null)
            throw new Exception("Property not found");
    
        retList = list.Select(c => prop.GetValue(c).ToString()).ToList();
        return retList;
    }
    

    并称之为:

    var result = GetResult(context.LP_Specification, "FieldName");
    
  • 0

    如果列数基本上是静态的,您应该可以尝试这样做 . 这消除了对反射和复杂表达树的需求;

    // this will be used in all querys; add 'where' clauses etc if you want
    IQueryable<Specification> rootQuery = from s in specification select s;
    
    IQueryable<string> names = null;
    switch(fieldName)
    {
        case "field1": names = rootQuery.Select(r => r.field1); break;
        case "field2": names = rootQuery.Select(r => r.field2); break;
        case "field3": names = rootQuery.Select(r => r.field3); break;
        default: throw new ArgumentOutOfRangeException("Unknown field: " + fieldName);
    }
    
    var strings = names.Distinct().ToList();
    

相关问题