使用表达式和字典的列映射
Column Mapping Using Expressions and Dictionary
我在为 IQueryable
对象编写表达式时遇到问题。我想不出使用表达式将字符串映射到对象属性的正确方法。
这是我的查询对象和映射字典:
var query = context.Industries.AsQueryable();
var columnsMap = new Dictionary<string, Expression<Func<Industry, object>>>()
{
["name"] = v => v.Name,
["isicCode"] = v => v.IsicCode.Data,
["isicCodeTitle"] = v => v.IsicCode.Title,
["isActive"] = v => v.IsActive,
};
并且我正在使用 columnsMap
字典将 Orderby
应用到我在扩展 class:
中的查询
public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, IQueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
{
if (String.IsNullOrWhiteSpace(queryObj.SortBy) || !columnsMap.ContainsKey(queryObj.SortBy))
return query;
if (queryObj.IsSortAsc)
return query.OrderBy(columnsMap[queryObj.SortBy]);
else
return query.OrderByDescending(columnsMap[queryObj.SortBy]);
}
对于 OrderBy
没问题,但我需要为 ApplyFiltering
做同样的事情但是为了过滤一个 IQueryable
对象,我需要一个不同的表达式来表示方法 Expression<Func<T, bool>>
public static IQueryable<T> ApplyFiltering<T>(this IQueryable<T> query, IQueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
{
query.Where(columnsMap['name'] == "test Name"); //this is the problem.
return query;
}
问题是如何在 ApplyFiltering 方法中使用我的 columnsMap?或者我应该为此更改我的 columnsMap 吗?
很简单。唯一的问题是当你有一个值类型列(例如 int
或 bool
或 DateTime
时)...... Expression<Func<Industry, object>>
将引入装箱field/property 到 object
我们必须删除。此问题已存在 string
秒。
// isActive is a bool
Expression<Func<Industry, object>> exp = columnsMap["isActive"];
object value = true; // You can't use "true" (string) here! isActive is a bool
// Other exammple
// Expression<Func<Industry, object>> exp = columnsMap["name"];
// object value = "Foo";
var body = exp.Body;
// Remove the boxing for value types
if (body.NodeType == ExpressionType.Convert)
{
body = ((UnaryExpression)body).Operand;
}
var eq = Expression.Equal(body, Expression.Constant(value, body.Type));
var exp2 = Expression.Lambda<Func<T, bool>>(eq, exp.Parameters);
return query.Where(exp2);
示例使用 string value
:
Expression<Func<Industry, object>> exp = columnsMap["isActive"];
string value = "true";
// Other exammple
//Expression<Func<Industry, object>> exp = columnsMap["name"];
//string value = "Foo";
var body = exp.Body;
// Remove the boxing for value types
if (body.NodeType == ExpressionType.Convert)
{
body = ((UnaryExpression)body).Operand;
}
object value2 = value;
if (value2 != null && body.Type != value2.GetType())
{
value2 = Convert.ChangeType(value2, body.Type);
}
var eq = Expression.Equal(body, Expression.Constant(value2, body.Type));
var exp2 = Expression.Lambda<Func<Industry, bool>>(eq, exp.Parameters);
return query.Where(exp2);
我在为 IQueryable
对象编写表达式时遇到问题。我想不出使用表达式将字符串映射到对象属性的正确方法。
这是我的查询对象和映射字典:
var query = context.Industries.AsQueryable();
var columnsMap = new Dictionary<string, Expression<Func<Industry, object>>>()
{
["name"] = v => v.Name,
["isicCode"] = v => v.IsicCode.Data,
["isicCodeTitle"] = v => v.IsicCode.Title,
["isActive"] = v => v.IsActive,
};
并且我正在使用 columnsMap
字典将 Orderby
应用到我在扩展 class:
public static IQueryable<T> ApplyOrdering<T>(this IQueryable<T> query, IQueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
{
if (String.IsNullOrWhiteSpace(queryObj.SortBy) || !columnsMap.ContainsKey(queryObj.SortBy))
return query;
if (queryObj.IsSortAsc)
return query.OrderBy(columnsMap[queryObj.SortBy]);
else
return query.OrderByDescending(columnsMap[queryObj.SortBy]);
}
对于 OrderBy
没问题,但我需要为 ApplyFiltering
做同样的事情但是为了过滤一个 IQueryable
对象,我需要一个不同的表达式来表示方法 Expression<Func<T, bool>>
public static IQueryable<T> ApplyFiltering<T>(this IQueryable<T> query, IQueryObject queryObj, Dictionary<string, Expression<Func<T, object>>> columnsMap)
{
query.Where(columnsMap['name'] == "test Name"); //this is the problem.
return query;
}
问题是如何在 ApplyFiltering 方法中使用我的 columnsMap?或者我应该为此更改我的 columnsMap 吗?
很简单。唯一的问题是当你有一个值类型列(例如 int
或 bool
或 DateTime
时)...... Expression<Func<Industry, object>>
将引入装箱field/property 到 object
我们必须删除。此问题已存在 string
秒。
// isActive is a bool
Expression<Func<Industry, object>> exp = columnsMap["isActive"];
object value = true; // You can't use "true" (string) here! isActive is a bool
// Other exammple
// Expression<Func<Industry, object>> exp = columnsMap["name"];
// object value = "Foo";
var body = exp.Body;
// Remove the boxing for value types
if (body.NodeType == ExpressionType.Convert)
{
body = ((UnaryExpression)body).Operand;
}
var eq = Expression.Equal(body, Expression.Constant(value, body.Type));
var exp2 = Expression.Lambda<Func<T, bool>>(eq, exp.Parameters);
return query.Where(exp2);
示例使用 string value
:
Expression<Func<Industry, object>> exp = columnsMap["isActive"];
string value = "true";
// Other exammple
//Expression<Func<Industry, object>> exp = columnsMap["name"];
//string value = "Foo";
var body = exp.Body;
// Remove the boxing for value types
if (body.NodeType == ExpressionType.Convert)
{
body = ((UnaryExpression)body).Operand;
}
object value2 = value;
if (value2 != null && body.Type != value2.GetType())
{
value2 = Convert.ChangeType(value2, body.Type);
}
var eq = Expression.Equal(body, Expression.Constant(value2, body.Type));
var exp2 = Expression.Lambda<Func<Industry, bool>>(eq, exp.Parameters);
return query.Where(exp2);