まず第一に、私の悪い英語で申し訳ありませんが、私の母国語ではありません。
私の仕事でASP.NETMVCプロジェクトでjqgridを使用していますが、検索を実装するときにいくつかの問題があります。私はLinqExtensionsを使用してインターネット上で見つける1つの解決策を使用しようとします。この問題は、エンティティに次のようなnull許容値がある場合に発生します。
public class MyClass()
{
string StringValue { get; set; }
int? IntegerValue { get; set; }
}
これは、データベースで値がnullを受け入れ、プロジェクトの他の理由でc#コードにnull許容値が必要なためです。
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);
}
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
{
.
.
.
}
}
グリッドを作成し、値を非常に正確に表示しますが...文字列で検索すると、一部の値がnullであっても問題が発生し、IntegerValue(nullをサポート)で検索しようとすると、エンティティの一部の値がnullの場合に例外がスローされます。この問題は私を狂った男に変えています。
どうか、同じ問題があるか、それを解決する方法を知っているなら、私は永遠に感謝します
さよなら