グリッド内の 2 つの列でいくつかのエラーを解決するのに問題があります。いくつかのテーブルを含むサンプル DB を作成し、jqGrid テスト アプリケーションを作成してデータを表示しました。グリッド上のデータを検索/フィルタリングしたかったのです。Oleg の MVC による検索とフィルタリングの例を使用しました。最初の 2 つの列 (ID、イベント タイトル) は問題なく機能しますが、それ以降の列は機能しません。何かが欠けていると確信していますが、何が欠けているのかわかりません。どんな助けでも素晴らしいでしょう。以下はコードです。
クライアント側:
var myGrid = $('#list'),
decodeErrorMessage = function (jqXHR, textStatus, errorThrown) {
var html, errorInfo, i, errorText = textStatus + '\n' + errorThrown;
if (jqXHR.responseText.charAt(0) === '[') {
try {
errorInfo = $.parseJSON(jqXHR.responseText);
errorText = "";
for (i = 0; i < errorInfo.length; i++) {
if (errorText.length !== 0) {
errorText += "<hr />";
}
errorText += errorInfo[i].Source + ": " + errorInfo[i].Message;
}
}
catch (e) { }
} else {
html = /<body.*?>([\s\S]*)<\/body>/.exec(jqXHR.responseText);
if (html !== null && html.length > 1) {
errorText = html[1];
}
}
return errorText;
};
myGrid.jqGrid({
url: '../Admin/GetEventsGridData/',
datatype: 'json',
mtype: 'POST',
colNames: ['ID', 'Event Title', 'Series', 'Occ', 'Department' ],
colModel: [
{ name: 'EVENT_ID', index: 'EVENT_ID', editable: true, editoptions: { readonly: 'readonly' }, width: 25, searchoptions: { sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge']} },
{ name: 'EVENT_TITLE', index: 'EVENT_TITLE', editable: true, width: 205, searchoptions: { sopt: ['cn', 'nc', 'bw', 'bn', 'eq', 'ne', 'ew', 'en', 'lt', 'le', 'gt', 'ge']} },
{ name: 'SERIES_DESCRIPTION', index: 'SERIES_DESCRIPTION', editable: true, width: 30, searchoptions: { sopt: ['cn', 'nc', 'bw', 'bn', 'eq', 'ne', 'ew', 'en', 'lt', 'le', 'gt', 'ge']} },
{ name: 'OCCURRENCES', index: 'OCCURRENCES', editable: true, width: 20, searchoptions: { sopt: ['eq', 'ne', 'lt', 'le', 'gt', 'ge']} }
{ name: 'DEPARTMENT_NAME', index: 'DEPARTMENT_NAME', editable: true, width: 100, searchoptions: { sopt: ['cn', 'nc', 'bw', 'bn', 'eq', 'ne', 'ew', 'en', 'lt', 'le', 'gt', 'ge']} }
],
pager: '#pager',
autowidth: true,
height: 'auto',
rowNum: 10,
rowList: [5, 10, 20, 50],
sortname: 'EVENT_ID',
sortorder: "desc",
viewrecords: true,
caption: 'Events',
jsonReader: { cell: "" },
loadError: function (jqXHR, textStatus, errorThrown) {
// remove error div if exist
$('#' + this.id + '_err').remove();
// insert div with the error description before the grid
myGrid.closest('div.ui-jqgrid').before(
'<div id="' + this.id + '_err" style="max-width:' + this.style.width +
';"><div class="ui-state-error ui-corner-all" style="padding:0.7em;float:left;"><span class="ui-icon ui-icon-alert" style="float:left; margin-right: .3em;"></span><span style="clear:left">' +
decodeErrorMessage(jqXHR, textStatus, errorThrown) + '</span></div><div style="clear:left" /></div>')
},
loadComplete: function () {
// remove error div if exist
$('#' + this.id + '_err').remove();
}
});
myGrid.jqGrid('navGrid', '#pager', { add: true, edit: true, del: true, refresh: true },
updateDialog, // add a record
updateDialog, // edit a record
updateDialog, // delete a record
{multipleSearch: true, overlay: false, width: 460 });
myGrid.jqGrid('filterToolbar', { stringResult: true, searchOnEnter: true, defaultSearch: 'cn' });
myGrid.jqGrid('navButtonAdd', '#pager',
{ caption: "Filter", title: "Toggle Searching Toolbar",
buttonicon: 'ui-icon-pin-s',
onClickButton: function () { myGrid[0].toggleToolbar(); }
});
これは私のサーバー側です:
using System;
using System.Collections.Generic;
using System.Data.Objects;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Newtonsoft.Json;
//using System.Data.Entity.Infrastructure;
using CATS.Models;
namespace CATS.Controllers
{
// to send exceptions as json we define [HandleJsonException] attribute
public class ExceptionInformation
{
public string Message { get; set; }
public string Source { get; set; }
public string StackTrace { get; set; }
}
public class HandleJsonExceptionAttribute : ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
{
filterContext.HttpContext.Response.StatusCode =
(int)System.Net.HttpStatusCode.InternalServerError;
var exInfo = new List<ExceptionInformation>();
for (Exception ex = filterContext.Exception; ex != null; ex = ex.InnerException)
{
PropertyInfo propertyInfo = ex.GetType().GetProperty("ErrorCode");
exInfo.Add(new ExceptionInformation()
{
Message = ex.Message,
Source = ex.Source,
StackTrace = ex.StackTrace
});
}
filterContext.Result = new JsonResult() { Data = exInfo };
filterContext.ExceptionHandled = true;
}
}
}
public class Filters
{
public enum GroupOp
{
AND,
OR
}
public enum Operations
{
eq, // "equal"
ne, // "not equal"
lt, // "less"
le, // "less or equal"
gt, // "greater"
ge, // "greater or equal"
bw, // "begins with"
bn, // "does not begin with"
//in, // "in"
//ni, // "not in"
ew, // "ends with"
en, // "does not end with"
cn, // "contains"
nc // "does not contain"
}
public class Rule
{
public string field { get; set; }
public Operations op { get; set; }
public string data { get; set; }
}
public GroupOp groupOp { get; set; }
public List<Rule> rules { get; set; }
private static readonly string[] FormatMapping = {
"(it.{0} = @p{1})", // "eq" - equal
"(it.{0} <> @p{1})", // "ne" - not equal
"(it.{0} < @p{1})", // "lt" - less than
"(it.{0} <= @p{1})", // "le" - less than or equal to
"(it.{0} > @p{1})", // "gt" - greater than
"(it.{0} >= @p{1})", // "ge" - greater than or equal to
"(it.{0} LIKE (@p{1}+'%'))", // "bw" - begins with
"(it.{0} NOT LIKE (@p{1}+'%'))", // "bn" - does not begin with
"(it.{0} LIKE ('%'+@p{1}))", // "ew" - ends with
"(it.{0} NOT LIKE ('%'+@p{1}))", // "en" - does not end with
"(it.{0} LIKE ('%'+@p{1}+'%'))", // "cn" - contains
"(it.{0} NOT LIKE ('%'+@p{1}+'%'))" //" nc" - does not contain
};
internal ObjectQuery<T> FilterObjectSet<T>(ObjectQuery<T> inputQuery) where T : class
{
if (rules.Count <= 0)
return inputQuery;
var sb = new StringBuilder();
var objParams = new List<ObjectParameter>(rules.Count);
foreach (Rule rule in rules)
{
PropertyInfo propertyInfo = typeof(T).GetProperty(rule.field);
if (propertyInfo == null)
continue; // skip wrong entries
if (sb.Length != 0)
sb.Append(groupOp);
var iParam = objParams.Count;
sb.AppendFormat(FormatMapping[(int)rule.op], rule.field, iParam);
ObjectParameter param;
switch (propertyInfo.PropertyType.FullName)
{
case "System.Int32": // int
param = new ObjectParameter("p" + iParam, Int32.Parse(rule.data));
break;
case "System.Int64": // bigint
param = new ObjectParameter("p" + iParam, Int64.Parse(rule.data));
break;
case "System.Int16": // smallint
param = new ObjectParameter("p" + iParam, Int16.Parse(rule.data));
break;
case "System.SByte": // tinyint
param = new ObjectParameter("p" + iParam, SByte.Parse(rule.data));
break;
case "System.Single": // Edm.Single, in SQL: float
param = new ObjectParameter("p" + iParam, Single.Parse(rule.data));
break;
case "System.Double": // float(53), double precision
param = new ObjectParameter("p" + iParam, Double.Parse(rule.data));
break;
case "System.Boolean": // Edm.Boolean, in SQL: bit
param = new ObjectParameter("p" + iParam,
String.Compare(rule.data, "1", StringComparison.Ordinal) == 0 ||
String.Compare(rule.data, "yes", StringComparison.OrdinalIgnoreCase) == 0 ||
String.Compare(rule.data, "true", StringComparison.OrdinalIgnoreCase) == 0);
break;
default:
// TODO: Extend to other data types
// binary, date, datetimeoffset,
// decimal, numeric,
// money, smallmoney
// and so on
param = new ObjectParameter("p" + iParam, rule.data);
break;
}
objParams.Add(param);
}
ObjectQuery<T> filteredQuery = inputQuery.Where(sb.ToString());
foreach (var objParam in objParams)
filteredQuery.Parameters.Add(objParam);
return filteredQuery;
}
}
[HandleJsonException]
public class AdminController : Controller
{
//
// GET: /Admin/
public ActionResult Admin()
{
ViewBag.PageTitle = "Admin";
return View();
}
public ActionResult GetEventsGridData(string sidx, string sord, int page, int rows, bool _search, string filters)
{
var context = new CATEntities();
//var context = new CATContext();
//var serializer = new JavaScriptSerializer();
//var objectContext = ((IObjectContextAdapter)context).ObjectContext;
//var eventset = objectContext.CreateObjectSet<EVENT>();
Filters f = (!_search || string.IsNullOrEmpty(filters)) ? null : JsonConvert.DeserializeObject<Filters>(filters);
ObjectQuery<EVENT> filteredQuery = (f == null ? context.EVENT : f.FilterObjectSet(context.EVENT)); // (ObjectQuery<EVENT>)eventset)
filteredQuery.MergeOption = MergeOption.NoTracking; // we don't want to update the data
var totalRecords = filteredQuery.Count();
var pagedQuery = filteredQuery.Skip("it." + sidx + " " + sord, "@skip",
new ObjectParameter("skip", (page - 1) * rows))
.Top("@limit", new ObjectParameter("limit", rows));
// to be able to use ToString() below which does NOT exist in the LINQ to Entity
var queryDetails = (from item in pagedQuery
select new { item.EVENT_ID, item.EVENT_TITLE, item.EVENT_SERIES.SERIES_DESCRIPTION, item.OCCURRENCES, item.DEPARTMENT.DEPARTMENT_NAME }).ToList();
return Json(new
{
total = (totalRecords + rows - 1) / rows,
page,
records = totalRecords,
rows = (from item in queryDetails
select new[] {
item.EVENT_ID.ToString(),
item.EVENT_TITLE,
item.SERIES_DESCRIPTION,
item.OCCURRENCES.ToString()
item.DEPARTMENT_NAME
}).ToList()
});
}
public ActionResult UpdateGridData(FormCollection formCollection)
{
return Json(JsonRequestBehavior.AllowGet);
}
}
}
私の問題は、Occurrences 列で次のエラーが発生することです。
System.Data.Entity: The argument types 'Edm.Int32' and 'Edm.String' are incompatible for this operation. Near equals expression, line 6, column 17.
Occurrences 列のデータはすべて整数データです。これは、整数データを探しているが、文字列データを送信していることを示しています。この列は EVENT_ID 列と同じです。切断がどこにあるのかわかりません。
シリーズ列にも問題があります。Event テーブルの Series 列は、シリーズ テーブルの外部キー ID です。そこから、シリーズの説明を取得しています。Department 列も同様です。これらの 2 つの列で検索/フィルター処理を実行しようとすると、次のエラーが発生します。
System.Data.Entity: You must specify a valid predicate for filtering the results. Parameter name: predicate
私は何かを失っていますが、私の人生ではそれを見つけることができません。