Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从具有动态列名的实体框架中选择不同的列_C#_Entity Framework - Fatal编程技术网

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

C# 从具有动态列名的实体框架中选择不同的列,c#,entity-framework,C#,Entity Framework,我正在寻找一种方法,为表中的一列获取不同值的列表。我需要制作一个可重用的方法 这是我迄今为止尝试过的,但不起作用: IEnumerable<string> GetDistinctValues<T>(string columnName) { T.Select(m => m.ColumnName).Distinct().ToList(); } IEnumerable GetDistinctValue(string columnName) { T.Select(

我正在寻找一种方法,为表中的一列获取不同值的列表。我需要制作一个可重用的方法

这是我迄今为止尝试过的,但不起作用:

IEnumerable<string> GetDistinctValues<T>(string columnName)
{
    T.Select(m => m.ColumnName).Distinct().ToList();
}
IEnumerable GetDistinctValue(string columnName)
{
T.Select(m=>m.ColumnName).Distinct().ToList();
}
理想的解决方案应该是EF对象的扩展方法


我试过这篇文章,但它只对一条记录有效,对一个列表无效。

我看到的
Linq.Dynamic
的唯一问题是,自2013年以来没有任何更新,而且项目几乎没有进展

我将通过扩展来处理它,并通过缓存来提高反射性能(这里没有详细说明)

扩展名:

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);
    }
}
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");
公共静态类QueryableExtensions
{
公共静态IReadOnlyCollection GetDistinctValuesForProperty(此IQueryable查询,表达式属性Access)
{
返回SelectDistinct(查询、属性访问).ToList();
}
公共静态IReadOnlyCollection GetDistinctValuesForProperty(此IQueryable查询,字符串propertyName)
{
var unboundFuncType=typeof(Func);
var unboundExprType=typeof(表达式);
var sourceType=typeof(TSource);//TSource
var resultType=typeof(TSource)
.GetProperty(propertyName)
.PropertyType;//TResult
//Func
var funcType=unboundFuncType.MakeGenericType(新[]{sourceType,resultType});
//表情
var expressionType=unboundExprtType.MakeGenericType(新[]{funcType});
//表达式的实例,例如x=>x.Name
var propertyAccess=typeof(StringExtensions)
.GetMethod(nameof(StringExtensions.AsPropertyExpression),new[]{typeof(string)})
.MakeGenericMethod(新[]{sourceType,resultType})
.Invoke(null,新对象[]{propertyName});
//选择不同的查询转换
var selectDistinctMethod=typeof(QueryableExtensions)
.GetMethod(nameof(QueryableExtensions.SelectDistinct)、BindingFlags.NonPublic | BindingFlags.Static)
.MakeGenericMethod(新[]{sourceType,resultType});
//IQueryable==>IQueryable
var result=selectDistinctMethod.Invoke(null,新对象[]{query,propertyAccess});
//通过IEnumerable转换为对象并转换为列表
返回((IEnumerable)结果).Cast().ToList();
}
专用静态IQueryable SelectDistinct(此IQueryable查询,表达式属性访问)
{
返回query.Select(propertyAccess.Distinct();
}
}
公共静态类扩展
{
公共静态表达式AsPropertyExpression(此字符串propertyName)
{
var参数=表达式参数(类型为(T),“x”);
var property=typeof(T).GetProperty(propertyName);
var body=Expression.MakeMemberAccess(参数、属性);
返回表达式.Lambda(主体,参数);
}
}
用法:

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);
    }
}
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");
公共类人物
{
公共字符串名称{get;}
公共整数{get;}
公众人物(字符串名称,整数年龄)
{
名称=名称;
年龄=年龄;
}
}
var people=新人[]
{
新人(“约翰”,25岁),新人(“彼得”,25岁),新人(“肖恩”,25岁),
新人(“约翰”,32岁),新人(“彼得”,32岁),
};
var query=people.AsQueryable();
var namePropertyExpression=“Name”.AsPropertyExpression();
var agePropertyExpression=“Age”.aspPropertyExpression();
//当您知道结果类型时
var names1=query.GetDistinctValuesForProperty(x=>x.Name);
var ages1=query.GetDistinctValuesForProperty(x=>x.Age);
//当您知道结果类型,但可能希望重用属性表达式时
var names2=query.GetDistinctValuesForProperty(namePropertyExpression);
var ages2=query.GetDistinctValuesForProperty(agePropertyExpression);
//当你只知道属性名的时候
var names3=query.GetDistinctValuesForProperty(“名称”);
var ages3=query.GetDistinctValuesForProperty(“年龄”);

我终于找到了解决办法。我需要包括对System.Linq.Dynamic(由nuget下载)的引用,并使用“选择”方法来接受字符串以引用列

using System.Linq.Dynamic;

public static async Task<IEnumerable<Object>> GetDistinctValuesForProperty<T>(this IQueryable<T> query, String PropertyName)
  {
  return await query.Select(PropertyName).Distinct().ToListAsync();
  }
使用System.Linq.Dynamic;
公共静态异步任务GetDistinctValuesForProperty(此IQueryable查询,字符串PropertyName)
{
return wait query.Select(PropertyName).Distinct().ToListSync();
}
并称为

String ColumnName = "DateTimeInsert";
DbSet<Log> oDbSet = _uow.DbContext.Set<Log>();

Array DistinctValues;
if (typeof(Log).GetProperty(ColumnName) != null)
  {
  DistinctValues = (await oDbSet.GetDistinctValuesForProperty(ColumnName)).ToArray();
  }
else
  {
  DistinctValues = new object[0];
  }
String ColumnName=“DateTimeInsert”;
DbSet oDbSet=_uow.DbContext.Set();
数组差异值;
if(typeof(Log).GetProperty(ColumnName)!=null)
{
DistinctValues=(等待oDbSet.GetDistinctValuesForProperty(ColumnName)).ToArray();
}
其他的
{
DistinctValues=新对象[0];
}

由于datetime类型的强制转换问题,我需要使用array vs ienumerable

您可以使用
表达式创建通用选择器方法

public static Func<T, T> SelectorFunc<T>(string[] columns) {
// input parameter "o"
var xParameter = Expression.Parameter(typeof(T), "o");

// new statement "new Data()"
var xNew = Expression.New(typeof(T));

// create initializers
var bindings = columns.Select(o => o.Trim())
 .Select(o =>
    {

        // property "Field1"
        var mi = typeof(T).GetProperty(o);

        // original value "o.Field1"
        var xOriginal = Expression.Property(xParameter, mi);

        // set value "Field1 = o.Field1"
    return Expression.Bind(mi, xOriginal);
        }
        );

    // initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var xInit = Expression.MemberInit(xNew, bindings);

        // expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
        var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

       // compile to Func<Data, Data>
     return lambda.Compile();
}

public static Func SelectorFunc(字符串[]列){
//输入参数“o”
var xParameter=表达式参数(typeof(T),“o”);
//新语句“newdata()”
var xNew=Expression.New(typeof(T));
//创建初始值设定项
var bindings=columns.Select(o=>o.Trim())
.选择(o=>
{
//属性“字段1”
var mi=typeof(T).GetProperty(o);
//原始值“o.Field1”
var xOriginal=Expression.Property(xParameter,mi);
//设置值“Field1=o.Field1”
返回表达式.Bind(mi,xOriginal);
}
);
//初始化“新数据{Field1=o.Field1,Field2=o.Field2}”
var xInit=Expression.MemberInit(xNew,bindings);
//表达式“o=>新数据{Field1=o.Field1,Field2=o.Field2}”
var lambda=表达式.lambda(xInit,xParameter);
//编译成Func
返回lambda.Compile();
}
使用它将是

T.Select( SelectorFunc<T>( new string[]{ "Column" } ) ).Distinct().ToList();
T.Select(SelectorFunc(新字符串[]{“列”})).Di