1

我有一个将 JSON 返回到 jQuery 数据表的操作。返回的数据可以根据传递给它的参数进行过滤。这是代码:

public ActionResult IndexAjaxHandler(jQueryDataTableParamModel parameters) {
    var data = _mailingListRep.GetAllWithinAccount();
    IEnumerable<MailingList> filtered;

    // Filtering - THIS DOES NOT WORK!
    if (!string.IsNullOrEmpty(parameters.sSearch)) {
        filtered = data.Where(c => 
            c.MailingListName.Contains(parameters.sSearch) ||
            ((c.IsDoubleOptIn) ? "Yes" : "No").Contains(parameters.sSearch, StringComparison.OrdinalIgnoreCase) ||
            c.Created.ToString("dd MMM yyyy").Contains(parameters.sSearch) ||
            c.ActiveMembers.Count().ToString().Contains(parameters.sSearch) ||
        c.AvailableSegments.Count().ToString().Contains(parameters.sSearch)
        );
    }
    else {
        filtered = data;
    }

    // create json object
    // return;
}

问题是这给了我以下错误:

方法 'Boolean Contains(System.String, System.String, System.StringComparison)' 不支持对 SQL 的转换。

在同一个控制器中是另一个操作,它也将 JSON 返回到数据表,它使用完全相同的过滤方法并且工作正常!

public ActionResult ViewDeletedAjaxHandler(int id, jQueryDataTableParamModel parameters) {
    var list = _mailingListRep.GetByIDWithinAccount(id);
    var data = list.DeletedMembers;
    IEnumerable<MailingListMember> filtered;

    // Filtering - THIS WORKS, NO ERRORS!
    if (!string.IsNullOrEmpty(parameters.sSearch)) {
        filtered = data.Where(c => 
            c.EmailAddress.Contains(parameters.sSearch, StringComparison.OrdinalIgnoreCase) ||
            c.UnsubscribedDate.ToString("dd MMM yyyy").Contains(parameters.sSearch, StringComparison.OrdinalIgnoreCase)
        );
    }
    else {
        filtered = data;
    }

    // create json object
    // return;
}

有人知道为什么是这样吗?

供参考,Contains(string, comparison)是一种扩展方法:

public static bool Contains(this string source, string toCheck, StringComparison comp) {
    return source.IndexOf(toCheck, comp) >= 0;
}

我理解错误的含义,这是代码在 1 个动作中工作的事实,但不是让我完全困惑。

感谢您提前提供任何帮助。

4

2 回答 2

2

您的第一个不起作用的过滤器应用于 a IQueryable<T>,而您的第二个起作用的过滤器应用于IEnumerable<T>. 当应用于 anIQueryable<T>时,过滤器必须可转换为 SQL,而当它用于 an 时IEnumerable<T>,过滤器在内存中进行评估。

要使第一个工作正常,您需要在应用过滤器之前ToList()调用以将结果强制存储到内存中,或者使用类中可用的辅助方法。EntityFunctions

于 2012-06-29T10:57:38.660 回答
1

如果数据引用的运行时类型在这两种情况下不同,则可以采用一种方法。

例如,如果它们都具有编译时类型IEnumerable<T>,但一个具有将 LINQ 变为 LINQ2SQL 的运行时类型,而另一个将其变为 LINQ2Object。包含后者但不包含前者的作品

IEnumerable<Entity> data = db.GetMyLazilyEvaluatedListOfEntities();
//this will fail
data.Where(e => e.Foo.Contains("bar"));
data = new List<Entity>();
//this will work
data.Where(e => e.Foo.Contains("bar"));

wheredb.GetMyLazilyEvaluatedListOfEntities返回一个对象,该对象实现IQueryable<Entity>在评估时将被转换为 SQL

如果data.ToList()在 where 之前调用,则可以避免运行时异常。但是,这将从数据库中获取整个表并在内存中进行过滤。如果该表的行数很少,这应该是一个非常值得关注的问题,但是如果您希望数据库表支持数据中有大量记录,您应该重写为可以转换为 SQL 的内容

于 2012-06-29T10:55:43.517 回答