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

时间:2016-09-13 07:06:47

标签: c# linq

所以我想从表中返回一个唯一值类型的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 个答案:

答案 0 :(得分: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 :(得分: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");

答案 2 :(得分: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();