rda*_*rte 4 linq asp.net-mvc jquery jqgrid linq-extensions
首先,抱歉我的英语不好,不是我的母语.
我在我的工作中使用ASP.NET MVC项目上的jqgrid,并在实现搜索时遇到一些问题.我尝试使用一个使用LinqExtensions在互联网上找到的解决方案.当实体具有可以为空的值时,问题就出现了:
public class MyClass()
{
string StringValue { get; set; }
int? IntegerValue { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
这是因为在数据库中,值接受null,并且由于项目上的其他原因需要我的c#代码上的可空值.
在另一个名为LinqExtensions的类中,where子句是这样的:
public static IQueryable<T> Where<T>(this IQueryable<T> source, string searchProperty, string searchString, string searchOper)
{
Type type = typeof(T);
if (string.IsNullOrEmpty(searchString))
return source;
ConstantExpression searchFilter = Expression.Constant(searchString.ToUpper());
ParameterExpression parameter = Expression.Parameter(type, "p");
//PropertyInfo property = type.GetProperty(searchProperty);
//Expression propertyAccess = Expression.MakeMemberAccess(parameter, property);
MemberExpression memberAccess = null;
String[] separador = {"__"};
foreach (var property2 in searchProperty.Split(separador, StringSplitOptions.None))
memberAccess = MemberExpression.Property
(memberAccess ?? (parameter as Expression), property2);
Expression propertyAccess = memberAccess;
if (propertyAccess.Type == typeof(Nullable<DateTime>))
{
PropertyInfo valProp = typeof(Nullable<DateTime>).GetProperty("Value");
propertyAccess = Expression.MakeMemberAccess(propertyAccess, valProp);
Nullable<DateTime> tn = DateTime.Parse(searchString);
searchFilter = Expression.Constant(tn);
}
//support int?
if (propertyAccess.Type == typeof(Nullable<Char>))
{
PropertyInfo valProp = typeof(Nullable<Char>).GetProperty("Value");
propertyAccess = Expression.MakeMemberAccess(propertyAccess, valProp);
Nullable<Char> tn = Char.Parse(searchString);
searchFilter = Expression.Constant(tn);
}
if (propertyAccess.Type == typeof(Nullable<Int16>))
{
PropertyInfo valProp = typeof(Nullable<Int16>).GetProperty("Value");
propertyAccess = Expression.MakeMemberAccess(propertyAccess, valProp);
Nullable<Int16> tn = Int16.Parse(searchString);
searchFilter = Expression.Constant(tn);
}
if (propertyAccess.Type == typeof(Nullable<Int32>))
{
PropertyInfo valProp = typeof(Nullable<Int32>).GetProperty("Value");
propertyAccess = Expression.MakeMemberAccess(propertyAccess, valProp);
Nullable<Int32> tn = Int32.Parse(searchString);
searchFilter = Expression.Constant(tn);
}
if (propertyAccess.Type == typeof(Nullable<Int64>))
{
PropertyInfo valProp = typeof(Nullable<Int64>).GetProperty("Value");
propertyAccess = Expression.MakeMemberAccess(propertyAccess, valProp);
Nullable<Int64> tn = Int64.Parse(searchString);
searchFilter = Expression.Constant(tn);
}
//support decimal?
if (propertyAccess.Type == typeof(Nullable<decimal>))
{
PropertyInfo valProp = typeof(Nullable<decimal>).GetProperty("Value");
propertyAccess = Expression.MakeMemberAccess(propertyAccess, valProp);
Nullable<decimal> tn = Decimal.Parse(searchString);
searchFilter = Expression.Constant(tn);
}
if (propertyAccess.Type == typeof(Char))
searchFilter = Expression.Constant(Char.Parse(searchString));
if (propertyAccess.Type == typeof(Int16))
searchFilter = Expression.Constant(Int16.Parse(searchString));
if (propertyAccess.Type == typeof(Int32))
searchFilter = Expression.Constant(Int32.Parse(searchString));
if (propertyAccess.Type == typeof(Int64))
searchFilter = Expression.Constant(Int64.Parse(searchString));
if (propertyAccess.Type == typeof(decimal))
searchFilter = Expression.Constant(Decimal.Parse(searchString));
if (propertyAccess.Type == typeof(DateTime))
searchFilter = Expression.Constant(DateTime.Parse(searchString));
MethodInfo startsWith = typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) });
MethodInfo endsWith = typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) });
MethodInfo contains = typeof(string).GetMethod("Contains", new Type[] { typeof(string) });
//MethodInfo contains = typeof(Int32Extensions).GetMethod("Contains", new Type[] { typeof(Int64), typeof(Int64) });
Expression operation = null;
switch (searchOper)
{
default:
case "eq":
operation = Expression.Equal(propertyAccess, searchFilter);
break;
case "ne":
operation = Expression.NotEqual(propertyAccess, searchFilter);
break;
case "lt":
operation = Expression.LessThan(propertyAccess, searchFilter);
break;
case "le":
operation = Expression.LessThanOrEqual(propertyAccess, searchFilter);
break;
case "gt":
operation = Expression.GreaterThan(propertyAccess, searchFilter);
break;
case "ge":
operation = Expression.GreaterThanOrEqual(propertyAccess, searchFilter);
break;
case "bw":
operation = Expression.Call(propertyAccess, startsWith, searchFilter);
break;
case "bn":
operation = Expression.Call(propertyAccess, startsWith, searchFilter);
operation = Expression.Not(operation);
break;
case "ew":
operation = Expression.Call(propertyAccess, endsWith, searchFilter);
break;
case "en":
operation = Expression.Call(propertyAccess, endsWith, searchFilter);
operation = Expression.Not(operation);
break;
case "cn":
operation = Expression.Call(propertyAccess, contains, searchFilter);
break;
case "nc":
operation = Expression.Call(propertyAccess, contains, searchFilter);
operation = Expression.Not(operation);
break;
}
var whereExpression = Expression.Lambda(operation, parameter);
var resultExpression = Expression.Call(typeof(Queryable), "Where", new Type[] { source.ElementType }, source.Expression, whereExpression);
return source.Provider.CreateQuery<T>(resultExpression);
}
Run Code Online (Sandbox Code Playgroud)
Model类中的方法是:
public JsonResult GetData(GridSettings grid)
{
if (Session["SomeValue"] != null)
{
var query = (new GridModel()).GetQuery();
//Filters
if (grid.IsSearch && grid.Where != null)
{
//And
if (grid.Where.groupOp == "AND")
foreach (var rule in grid.Where.rules)
query = query.Where<MyClass>(rule.field, rule.data.ToUpper(), rule.op);
else
{
//Or
var temp = (new List<MyClass>()).AsQueryable();
foreach (var rule in grid.Where.rules)
{
var t = query.Where<MyClass>(rule.field, rule.data, rule.op);
temp = temp.Concat<MyClass>(t);
}
//Clean repeat elements
query = temp.Distinct<MyClass>();
}
}
//Order
query = query.OrderBy<MyClass>(grid.SortColumn,
grid.SortOrder);
//Count
var count = query.Count();
//Pager
var data = query.Skip((grid.PageIndex - 1) * grid.PageSize).Take(grid.PageSize).ToArray();
//Convert
var result = new
{
.
.
.
}
}
Run Code Online (Sandbox Code Playgroud)
我创建网格,非常正确地显示值但是......当按字符串搜索任何问题时,即使某些值为空,如果尝试通过IntegerValue(支持null)进行搜索,并且当实体上的某些值为null时抛出Exception .这个问题正在改变我对一个疯狂的人.
如果有任何问题或知道如何解决,请永远感激
再见
它比我想象的更容易,最好的方法是覆盖调用表达式的运算符:
例如,在我的问题中,将equals方法覆盖为:
private static Expression LinqEqual(Expression e1, Expression e2)
{
if (IsNullableType(e1.Type) && !IsNullableType(e2.Type))
e2 = Expression.Convert(e2, e1.Type);
else if (!IsNullableType(e1.Type) && IsNullableType(e2.Type))
e1 = Expression.Convert(e1, e2.Type);
return Expression.Equal(e1, e2);
}
private static bool IsNullableType(Type t)
{
return t.IsGenericType && t.GetGenericTypeDefinition() == typeof(Nullable<>);
}
Run Code Online (Sandbox Code Playgroud)
并替换这段代码:
Expression operation = null;
switch (searchOper)
{
default:
case "eq":
operation = Expression.Equal(propertyAccess, searchFilter);
break;
.
.
.
}
Run Code Online (Sandbox Code Playgroud)
我希望问题和解决方案有所帮助.
谢谢Stackoverflow
| 归档时间: |
|
| 查看次数: |
1315 次 |
| 最近记录: |