簡體   English   中英

LINQ,使用動態字段名稱獲取字符串列表

[英]LINQ, get string list using dynamic field name

所以我想從表中返回具有唯一值的String類型的List。

值得注意的是,該表的設計者決定該表的每一行都具有多列且具有多個唯一字段。 因此,您不僅可以從表中獲得項目的唯一列表,還需要指定該字段然后變得與眾不同。

因此,為此,我想編寫一個通用方法,在其中可以指定列名稱並獲得唯一的項目列表。

我已經嘗試了以下兩種方法:

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)

我想從表中獲取字符串值的列表,只返回指定字段的不同值。

您不需要使用反射來獲取每個對象的屬性值,因為該查詢將針對數據庫執行,因此該方法將不起作用(除非在查詢內存中的集合的情況下)。

您需要構建動態表達式樹來實現所需的功能。 一個簡單的例子是這樣的:

// 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();

我認為您可以使用如下通用方法:

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");

如果列數基本上是靜態的,那么您應該可以嘗試一下。 這消除了對反射樹和復雜表達樹的需求;

// 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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM