C# #使用表达式扩展linq的Order by Not Null
我有一个自定义的IOrderedQueryable函数,如下所示C# #使用表达式扩展linq的Order by Not Null,c#,linq,lambda,iqueryable,C#,Linq,Lambda,Iqueryable,我有一个自定义的IOrderedQueryable函数,如下所示 public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> srcQuery, string orderColumn, bool isAscending) { var type = typeof(T); var property = type.GetProperty(orderColumn); if (prop
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> srcQuery,
string orderColumn, bool isAscending)
{
var type = typeof(T);
var property = type.GetProperty(orderColumn);
if (property == null)
throw new Exception("Column property \"" + orderColumn + "\" does not exist on the type \"" + typeof(T).FullName + "\"");
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.MakeMemberAccess(parameter, property);
var orderByExp = Expression.Lambda(propertyAccess, parameter);
MethodCallExpression resultExp =
Expression.Call(typeof(Queryable),isAscending ? "OrderBy" :
"OrderByDescending", new Type[] { type, property.PropertyType },
srcQuery.Expression, Expression.Quote(orderByExp));
return (IOrderedQueryable<T>)srcQuery.Provider.CreateQuery<T>(resultExp);
}
public static IOrderedQueryable OrderBy(此IQueryable srcQuery,
字符串顺序列,bool isAscending)
{
var类型=类型(T);
var property=type.GetProperty(orderColumn);
if(属性==null)
抛出新异常(“列属性\”“+orderColumn+“\”在类型\”“+typeof(T).FullName+“\”)上不存在);
var参数=表达式参数(类型为“p”);
var propertyAccess=Expression.MakeMemberAccess(参数,属性);
var orderByExp=Expression.Lambda(propertyAccess,参数);
MethodCallExpression resultExp=
Expression.Call(typeof(Queryable),isassending?“OrderBy”:
“OrderByDescending”,新类型[]{Type,property.PropertyType},
srcQuery.Expression,Expression.Quote(orderByExp));
返回(IOrderedQueryable)srcQuery.Provider.CreateQuery(resultExp);
}
我想知道是否有任何我可以做的条件属性的命令=null以在上述orderByExp表达式中首先显示非null值,然后显示null值您可以修改属性访问以执行与查询等价的操作。OrderBy(x=>x.property==null?0:1)
默认值可在DefaultTypeValues中按类型自定义,或者如果未指定任何值,则默认为基础的可为空类型(例如,对于
int?
它将为0)这在您的情况下不可能使用吗OrderBy(x=>x.property==null?0:1)
Hi Titian谢谢你的回复。我当前拥有的字段是可为空的日期时间。上面的方法也同样适用吗?应该适用于任何Nullable
,我刚刚用DateTime?
进行了测试,查询是正确生成的。对不起,我没有发布代码的最终版本。做一个小小的改变应该可以,但我现在不能测试,因为我在床上。如果它不起作用,请告诉我,我明天会找到解决方案。嗨,提香,非常感谢你的回复。我只是试着调试代码,前面提到的错误运行良好。但是现在我得到另一个错误,指出{“参数类型不匹配”}。当我有一个不可为空的属性-->{System.DateTime CreateDate}@rockingmeister Ok时,就会发生这种情况,但问题是在这种情况下,您希望它做什么。。因为最初的请求是按天气排序的,所以它是否为空。如果列为DateTime,则该列不能为空。。那么它应该做什么排序呢?
public static IOrderedQueryable<T> OrderByNull<T>(IQueryable<T> srcQuery, string orderColumn, bool isAscending)
{
var type = typeof(T);
var property = type.GetProperty(orderColumn);
if (property == null)
throw new Exception("Column property \"" + orderColumn + "\" does not exist on the type \"" + typeof(T).FullName + "\"");
var parameter = Expression.Parameter(type, "p");
var propertyAccess = Expression.Condition(
Expression.Equal(Expression.MakeMemberAccess(parameter, property), Expression.Constant(null, property.PropertyType)),
Expression.Constant(1),
Expression.Constant(0));
var orderByExp = Expression.Lambda(propertyAccess, parameter);
MethodCallExpression resultExp =Expression.Call( typeof(Queryable), isAscending ? "OrderBy" : "OrderByDescending", new Type[] { type, typeof(int) },
srcQuery.Expression, Expression.Quote(orderByExp));
return (IOrderedQueryable<T>)srcQuery.Provider.CreateQuery<T>(resultExp);
}
static Dictionary<Type, object> DefaultTypeValues = new Dictionary<Type, object>
{
{ typeof(string), "" },
// { typeof(DateTime?), new DateTime(1753,1,1) } // Min date for sql date
{ typeof(DateTime?), new DateTime(9999,12,31} // Max date for sql date
};
public static object GetDefaultValue(Type t)
{
object defaultValue;
if(!DefaultTypeValues.TryGetValue(t, out defaultValue))
{
if(t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>))
{
defaultValue = Activator.CreateInstance(t.GetGenericArguments().Single());
}
else
{
throw new NotSupportedException("Could not get default value for type " + t.FullName + " consider adding it in DefaultTypeValues");
}
}
return defaultValue;
}
public static IOrderedQueryable<T> OrderBy<T>(IQueryable<T> srcQuery, string orderColumn, bool isAscending)
{
var type = typeof(T);
var property = type.GetProperty(orderColumn);
if (property == null)
throw new Exception("Column property \"" + orderColumn + "\" does not exist on the type \"" + typeof(T).FullName + "\"");
var parameter = Expression.Parameter(type, "p");
// default sort is performed by o=> o.Prop
Expression propertyAccess = Expression.MakeMemberAccess(parameter, property);
var propType = property.PropertyType;
// If property is nullable we add teh null check
if (propType == typeof(string) || (propType.IsGenericType && propType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
var defaultValue = GetDefaultValue(propType);
// If the property is nullable we sort by (o => o.Prop == null ? default(propType) : o.Prop)
propertyAccess = Expression.Condition(
Expression.Equal(propertyAccess, Expression.Constant(null, propType)),
Expression.Constant(defaultValue, propType),
propertyAccess
);
}
var orderByExp = Expression.Lambda(propertyAccess, parameter);
MethodCallExpression resultExp = Expression.Call(typeof(Queryable), isAscending ? "OrderBy" : "OrderByDescending", new Type[] { type, propType },
srcQuery.Expression, Expression.Quote(orderByExp));
return (IOrderedQueryable<T>)srcQuery.Provider.CreateQuery<T>(resultExp);
}