首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从具有动态列名的实体框架中选择不同的列

从具有动态列名的实体框架中选择不同的列
EN

Stack Overflow用户
提问于 2017-08-02 17:12:30
回答 3查看 881关注 0票数 1

我正在寻找一种方法来获取表中某一列的不同值的列表。我需要创建一个可重用的方法。

这就是我到目前为止尝试的方法,但它不起作用:

代码语言:javascript
复制
IEnumerable<string> GetDistinctValues<T>(string columnName)
{
    T.Select(m => m.ColumnName).Distinct().ToList();
}

所需的解决方案应该是EF对象的扩展方法。

我试过这个帖子Dynamically select columns in runtime using entity framework,但它只适用于单个记录,不适用于列表。

EN

Stack Overflow用户

发布于 2017-08-02 17:24:30

我看到的Linq.Dynamic唯一的问题是,自2013年以来就没有更新过,这个项目几乎已经死亡

我会通过扩展来处理它,并通过缓存来提高反射性能(这里不再赘述)。

扩展:

代码语言:javascript
复制
public static class QueryableExtensions
{
    public static IReadOnlyCollection<TResult> GetDistinctValuesForProperty<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> propertyAccess)
    {
        return SelectDistinct(query, propertyAccess).ToList();
    }

    public static IReadOnlyCollection<object> GetDistinctValuesForProperty<TSource>(this IQueryable<TSource> query, string propertyName)
    {
        var unboundFuncType = typeof(Func<,>);
        var unboundExprType = typeof(Expression<>);

        var sourceType = typeof(TSource); // TSource

        var resultType = typeof(TSource)
            .GetProperty(propertyName)
            .PropertyType; // TResult

        // Func<TSource, TResult>
        var funcType = unboundFuncType.MakeGenericType(new [] { sourceType, resultType });

        // Expression<Func<TSource, TResult>>
        var expressionType = unboundExprType.MakeGenericType(new [] { funcType });

        // Instance of Expression<Func<TSource, TResult>>, for example x => x.Name
        var propertyAccess = typeof(StringExtensions)
            .GetMethod(nameof(StringExtensions.AsPropertyExpression), new[] { typeof(string) })
            .MakeGenericMethod(new [] { sourceType, resultType })
            .Invoke(null, new object[] { propertyName });

        // SelectDistinct query transform
        var selectDistinctMethod = typeof(QueryableExtensions)
            .GetMethod(nameof(QueryableExtensions.SelectDistinct), BindingFlags.NonPublic | BindingFlags.Static)
            .MakeGenericMethod(new [] { sourceType, resultType });

        // IQueryable<TSource> ==> IQueryable<TResult>
        var result = selectDistinctMethod.Invoke(null, new object[] { query, propertyAccess });

        // Cast to object via IEnumerable and convert to list
        return ((IEnumerable)result).Cast<object>().ToList();
    }

    private static IQueryable<TResult> SelectDistinct<TSource, TResult>(this IQueryable<TSource> query, Expression<Func<TSource, TResult>> propertyAccess)
    {
        return query.Select(propertyAccess).Distinct();
    }
}

public static class StringExtensions
{
    public static Expression<Func<T, TResult>> AsPropertyExpression<T, TResult>(this string propertyName)
    {
        var parameter = Expression.Parameter(typeof(T), "x");
        var property = typeof(T).GetProperty(propertyName);
        var body = Expression.MakeMemberAccess(parameter, property);
        return Expression.Lambda<Func<T, TResult>>(body, parameter);
    }
}

使用:

代码语言:javascript
复制
public class Person
{
    public string Name { get; }
    public int Age { get; }

    public Person(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

var people = new Person[]
{
    new Person("John", 25), new Person("Peter", 25), new Person("Sean", 25),
    new Person("John", 32), new Person("Peter", 32),
};

var query = people.AsQueryable();

var namePropertyExpression = "Name".AsPropertyExpression<Person, string>();
var agePropertyExpression = "Age".AsPropertyExpression<Person, int>();

// When you know the result type
var names1 = query.GetDistinctValuesForProperty(x => x.Name);
var ages1 = query.GetDistinctValuesForProperty(x => x.Age);

// When you know the result type, but you may want to reuse the property expression
var names2 = query.GetDistinctValuesForProperty(namePropertyExpression);
var ages2 = query.GetDistinctValuesForProperty(agePropertyExpression);

// When you just know the property name
var names3 = query.GetDistinctValuesForProperty("Name");
var ages3 = query.GetDistinctValuesForProperty("Age");
票数 3
EN
查看全部 3 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45456453

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档