我有一个调用Entity Framework函数的方法。它负责发送“select子句”,“order by clause”和可能包含(考虑到我正在使用延迟加载)。该方法如下所示:
public IEnumerable<TReturn> GetAll<TReturn, TOrderKey>(
Expression<Func<TEntity, TReturn>> selectExp,
Expression<Func<TEntity, TOrderKey>> orderbyExp,
Boolean descending,
params Expression<Func<TEntity, Object>>[] includeExps)
{
var query = DbSet.AsQueryable();
query = !descending ? query.OrderBy(orderByExp) : query.OrderByDescending(orderByExp);
if (includeExps != null)
query = includeExps.Aggregate(query, (current, exp) => current.Include(exp));
return query.Select(selectExp).ToList();
}
我打电话的时候:
_service.GetAll(i => new { i.Name}, i => i.Name, false, null);
工作正常!这就是生成的SQL就是我想要的。
然而,考虑到一个真实的场景(在我的情况下我使用的是asp.net mvc),我有一个Action方法从客户端获取order参数。
这就是方法:
public JsonResult GetAllUsers(string sortColumn, bool sortDescending)
{
//sortColumn string must be translated in a Expression
var users = _service.GetAll(i => new { i.Name, i.Email }, i => i.Name, sortDescending, null);
//
//
}
我的第一次尝试是为每一列创建一个表达式,如下所示:
public JsonResult GetAllUsers(string sortColumn, bool sortDescending)
{
//I don't what is the Type that I should put here
//It can be anything, like: Expression<Func<User, String>>,
//Expression<Func<User, Guid>>, Expression<Func<User, Int>>
?Type? orderExp;
switch(sortColumn)
{
case "UserId":
//Expression<Func<User, Guid>>
orderExp = i => i.UserId;
break;
case "Name":
//Expression<Func<User, String>>
orderExp = i => i.Email;
break;
}
//sortColumn string must be translated in a Expression
var users = _service.GetAll(i => new { i.Name, i.Email }, orderExp, sortDescending, null);
//
//
}
我想创建一个基于sortProperty的表达式,但是在stackoverflow上有很多关于它的信息,但是(参见action方法)变量必须在进程之前输入。无法在每个“case”中调用GetAll方法,因为它返回匿名类型。
我无法将所有列转换为Expression<Func<User, Object>>
,因为实体框架不支持它。
Linq.Dynamic应该有帮助,但我不想使用字符串参数。
答案 0 :(得分:0)
您可以按如下方式重载GetAll
方法:
public IEnumerable<TReturn> GetAll<TReturn>(
Expression<Func<TEntity, TReturn>> selectExp,
string orderColumnName,
Boolean descending,
params Expression<Func<TEntity, Object>>[] includeExps)
{
var entityType = typeof(TEntity);
var prop = entityType.GetProperty(orderColumnName);
var param = Expression.Parameter(entityType, "i");
var orderExp = Expression.Lambda(
Expression.MakeMemberAccess(param, prop), param);
// get the original GetAll method overload
var method = this.GetType().GetMethods().Where(m => m.Name == "GetAll" && m.GetGenericArguments().Length == 2);
var actualMethod = method.First().MakeGenericMethod(typeof(TReturn), prop.PropertyType);
return (IEnumerable<TReturn>)actualMethod.Invoke(this, new object[] { selectExp, orderExp, descending, includeExps });
}
只需为null
值添加一些检查,否则无效的sortColumn名称会回来困扰你。
使用它与您当前的方法类似:
_service.GetAll(i => new { i.Name, i.Email }, sortColumn, sortDescending, null);