C# 基于字符串字段名选择不同的实体值

C# 基于字符串字段名选择不同的实体值,c#,linq,entity-framework,C#,Linq,Entity Framework,在列名未知的情况下,是否可以选择实体的不同属性值?方法将其作为字符串从客户端接收 出于过滤目的,我想从浏览器向服务器发出HTTP POST Ajax请求,该请求将包含字段名作为键,并且该字段将作为字符串提供给服务器 我知道我必须手动映射ViewModel和Entity Framework使用的POCO类之间的任何差异,但是是否可以在不使用强类型属性的情况下构造实体框架查询?例如,使用反射 我可能会尝试在控制器确定数据的情况下实现这一点,以实体类作为类型调用基本存储库的通用方法。这是可能的还是我需

在列名未知的情况下,是否可以选择实体的不同属性值?方法将其作为字符串从客户端接收

出于过滤目的,我想从浏览器向服务器发出HTTP POST Ajax请求,该请求将包含字段名作为键,并且该字段将作为字符串提供给服务器

我知道我必须手动映射ViewModel和Entity Framework使用的POCO类之间的任何差异,但是是否可以在不使用强类型属性的情况下构造实体框架查询?例如,使用反射

我可能会尝试在控制器确定数据的情况下实现这一点,以实体类作为类型调用基本存储库的通用方法。这是可能的还是我需要为每个可能的字段构造一个方法

同样,我应该尝试这样做,还是用字段作为参数构造ADO.NET SQL命令(从ViewModel映射到SQL列名)?

我很确定最近看到了类似的答案,但我找不到它

如果您知道实体的类型和要选择的属性的类型,这非常简单:

public IQueryable<TProperty> SelectProperty<TEntity, TProperty>(DbContext context, string propertyName)
    where TEntity : class
{
    var parameter = Expression.Parameter(typeof(TEntity));
    var body = Expression.Property(parameter, propertyName);
    var lambda = Expression.Lambda<Func<TEntity, TProperty>>(body, parameter);
    var result = context.Set<TEntity>().Select (lambda).Distinct();

    return result;
}
公共IQueryable SelectProperty(DbContext上下文,字符串propertyName) 地点:班级 { var参数=表达式参数(typeof(tenty)); var body=Expression.Property(参数,propertyName); var lambda=表达式.lambda(主体,参数); var result=context.Set().Select(lambda.Distinct(); 返回结果; } 如果无法预测属性的类型,则构建表达式将更加困难:

public IQueryable SelectProperty<TEntity>(DbContext context, string propertyName)
    where TEntity : class
{
    var entities = context.Set<TEntity>();
    var query = entities.AsQueryable();
    var parameter = Expression.Parameter(typeof(TEntity), "instance");
    var propertyAccess = Expression.Property(parameter, propertyName);
    var projection = Expression.Lambda(propertyAccess, parameter);

    var selectExpression = Expression.Call(
        typeof(Queryable).GetMethods()
                         .First (x => x.Name == "Select")
                         .MakeGenericMethod(new[]{ typeof(TEntity), propertyAccess.Type }),
        query.Expression,
        projection);

    var distinctExpression = Expression.Call(
        typeof(Queryable).GetMethods()
                         .First (x => x.Name == "Distinct")
                         .MakeGenericMethod(new[]{ propertyAccess.Type }),
        selectExpression);

    var result = query.Provider.CreateQuery(distinctExpression);

    return result;
}
公共IQueryable SelectProperty(DbContext上下文,字符串propertyName) 地点:班级 { var entities=context.Set(); var query=entities.AsQueryable(); var参数=Expression.parameter(typeof(tenty),“instance”); var propertyAccess=Expression.Property(参数,propertyName); var projection=Expression.Lambda(propertyAccess,参数); var selectExpression=Expression.Call( typeof(可查询).GetMethods() .First(x=>x.Name==“选择”) .MakeGenericMethod(新[]{typeof(tenty),propertyAccess.Type}), query.Expression, 投影); var distinctExpression=Expression.Call( typeof(可查询).GetMethods() .First(x=>x.Name==“不同”) .MakeGenericMethod(新[]{propertyAccess.Type}), 选择表达); var result=query.Provider.CreateQuery(distinctExpression); 返回结果; } 我很确定最近我看到了类似的答案,但我找不到

如果您知道实体的类型和要选择的属性的类型,这非常简单:

public IQueryable<TProperty> SelectProperty<TEntity, TProperty>(DbContext context, string propertyName)
    where TEntity : class
{
    var parameter = Expression.Parameter(typeof(TEntity));
    var body = Expression.Property(parameter, propertyName);
    var lambda = Expression.Lambda<Func<TEntity, TProperty>>(body, parameter);
    var result = context.Set<TEntity>().Select (lambda).Distinct();

    return result;
}
公共IQueryable SelectProperty(DbContext上下文,字符串propertyName) 地点:班级 { var参数=表达式参数(typeof(tenty)); var body=Expression.Property(参数,propertyName); var lambda=表达式.lambda(主体,参数); var result=context.Set().Select(lambda.Distinct(); 返回结果; } 如果无法预测属性的类型,则构建表达式将更加困难:

public IQueryable SelectProperty<TEntity>(DbContext context, string propertyName)
    where TEntity : class
{
    var entities = context.Set<TEntity>();
    var query = entities.AsQueryable();
    var parameter = Expression.Parameter(typeof(TEntity), "instance");
    var propertyAccess = Expression.Property(parameter, propertyName);
    var projection = Expression.Lambda(propertyAccess, parameter);

    var selectExpression = Expression.Call(
        typeof(Queryable).GetMethods()
                         .First (x => x.Name == "Select")
                         .MakeGenericMethod(new[]{ typeof(TEntity), propertyAccess.Type }),
        query.Expression,
        projection);

    var distinctExpression = Expression.Call(
        typeof(Queryable).GetMethods()
                         .First (x => x.Name == "Distinct")
                         .MakeGenericMethod(new[]{ propertyAccess.Type }),
        selectExpression);

    var result = query.Provider.CreateQuery(distinctExpression);

    return result;
}
公共IQueryable SelectProperty(DbContext上下文,字符串propertyName) 地点:班级 { var entities=context.Set(); var query=entities.AsQueryable(); var参数=Expression.parameter(typeof(tenty),“instance”); var propertyAccess=Expression.Property(参数,propertyName); var projection=Expression.Lambda(propertyAccess,参数); var selectExpression=Expression.Call( typeof(可查询).GetMethods() .First(x=>x.Name==“选择”) .MakeGenericMethod(新[]{typeof(tenty),propertyAccess.Type}), query.Expression, 投影); var distinctExpression=Expression.Call( typeof(可查询).GetMethods() .First(x=>x.Name==“不同”) .MakeGenericMethod(新[]{propertyAccess.Type}), 选择表达); var result=query.Provider.CreateQuery(distinctExpression); 返回结果; } 您可以使用Dyanmic Linq(nuget包:System.Linq.Dynamic)来实现这一点,并找到了一个扩展方法,我甚至不想为它负责

示例代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace dlinq1
{
    class Thing
    {
        public int ID { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var things = new List<Thing>();
            for(int x=0;x<10;x++)
            {
                things.Add(new Thing{ID=x%2}); //0,1,0,1,0,1,0,1,0,1
            }
            var result = things.AsQueryable().Select("ID").Distinct();
            foreach (var r in result)
            {
                Console.WriteLine(r);
            }
            Console.ReadLine(); //produces 0, 1
        }
    }

    public static class DynamicQueryableExtras
    {
        public static IQueryable Distinct(this IQueryable q)
        {
            var call = Expression.Call(typeof(Queryable),
                                       "Distinct",
                                       new Type[] { q.ElementType },
                                       q.Expression);
            return q.Provider.CreateQuery(call);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Dynamic;
使用System.Linq.Expressions;
使用系统文本;
使用System.Threading.Tasks;
名称空间dlinq1
{
阶级事务
{
公共int ID{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
var things=newlist();
对于(intx=0;x您可以使用dyanmiclinq(nuget-package:System.Linq.Dynamic)来实现这一点,并找到了一种扩展方法,我甚至不想尝试将其归功于此

示例代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace dlinq1
{
    class Thing
    {
        public int ID { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {
            var things = new List<Thing>();
            for(int x=0;x<10;x++)
            {
                things.Add(new Thing{ID=x%2}); //0,1,0,1,0,1,0,1,0,1
            }
            var result = things.AsQueryable().Select("ID").Distinct();
            foreach (var r in result)
            {
                Console.WriteLine(r);
            }
            Console.ReadLine(); //produces 0, 1
        }
    }

    public static class DynamicQueryableExtras
    {
        public static IQueryable Distinct(this IQueryable q)
        {
            var call = Expression.Call(typeof(Queryable),
                                       "Distinct",
                                       new Type[] { q.ElementType },
                                       q.Expression);
            return q.Provider.CreateQuery(call);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用System.Linq.Dynamic;
使用System.Linq.Expressions;
使用系统文本;
使用System.Threading.Tasks;
名称空间dlinq1
{
阶级事务
{
公共int ID{get;set;}
}
班级计划
{
静态void Main(字符串[]参数)
{
var things=newlist();

对于(int x=0;x)旧的良好动态LINQ仍应与EF一起工作,为您提供所需。此处的类似问题:旧的良好动态LINQ仍应与EF一起工作,为您提供所需。此处的类似问题: