是否可以选择事先不知道列名的实体的不同属性值 - 由方法作为来自客户端的字符串接收。
出于过滤目的,我想从浏览器向服务器发出一个HTTP POST Ajax请求,该请求将包含字段名称作为密钥,这将作为字符串提供给服务器。
我知道我将不得不手动映射ViewModel和Entity Framework使用的POCO类之间的任何差异,但是可以构造一个没有强类型属性的实体框架查询 - 例如使用反射。 / p>
我可能会尝试实现这一点,其中数据由控制器确定,调用基础存储库的泛型方法,实体类作为类型。这是可能的还是我需要为每个可能的字段构建一个方法?
同样,我应该尝试这样做,还是以字段作为参数构建ADO.NET SQL命令(从ViewModel映射到SQL列名称)?
答案 0 :(得分:6)
我很确定我最近看到了类似的答案,但我找不到它......
如果您知道实体的类型以及您要选择的属性类型,这很容易:
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;
}
如果无法预测属性的类型,那么构建表达式将更加困难:
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;
}
答案 1 :(得分:0)
您可以使用Dyanmic Linq(nuget包:System.Linq.Dynamic)执行此操作,以及我甚至不会尝试使用的扩展方法,找到here
示例代码:
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);
}
}
}
基本上,扩展名适用于自您在调用Distinct之前的前一个表达式以来查询所处的状态。