【问题标题】:"Only arguments that can be evaluated on the client are supported for the String.Contains method"“String.Contains 方法仅支持可以在客户端上评估的参数”
【发布时间】:2009-11-09 20:57:19
【问题描述】:
public static void MyFunction(MyErrorClass err)
{
    var query = from filter in DataContext.ErrorFilters select filter;
    query = query.Where(f => err.ErrorMessage.Contains(f.ErrorMessage));
    List<ErrorFilter> filters = query.ToList();
    //...more code
}

所以我在上面的代码中遇到了一些问题,并且我从主题行中的query.ToList() 行中得到了错误。这是我正在尝试做的事情:

首先,我有一个自定义错误类MyErrorClass。每当我的网站发生错误时,我都会从异常中创建一个MyErrorClass 对象,将异常中的所有数据存储在该对象中,并将信息存储在数据库中。

我正在跟踪的异常属性之一是错误消息 (ErrorMessage)。我在数据库中设置了一个ErrorFilters 表,用户可以在其中根据ErrorMessage 过滤错误。因此,假设您收到大量错误,上面写着“System.Data.SqlClient.SqlException:超时已过期。在操作完成之前超时时间已过或服务器没有响应。”,您想忽略它们。您只需向数据库添加一个过滤器,错误消息为“超时已过期”,并将其设置为忽略。

现在,我上面的类设置为接受错误,并决定是否应该过滤错误。我正在尝试获取具有与错误匹配的ErrorMessage 的所有过滤器的列表。

我确定这很容易解决,我只是不知道如何解决。

【问题讨论】:

  • 这个方法返回void,应该怎么做?如果它必须检查是否必须显示错误,那么它应该返回一个布尔值,并且可以找到修复。否则,请更好地解释这个问题。
  • 该函数正在执行许多与错误无关的其他事情,重要的是我试图获取与错误匹配的过滤器列表的那 3 行。我解释了你需要知道的一切,你还想知道什么?

标签: c# asp.net linq linq-to-sql


【解决方案1】:

嗯...看起来 Linq2SQL IndexOf 的翻译比 Contains 更智能。这应该有效:

public static void MyFunction(MyErrorClass err)
{
    var query = DataContext.ErrorFilters;
    query = query.Where(f => err.ErrorMessage.IndexOf(f.ErrorMessage)>=0);
    List<ErrorFilter> filters = query.ToList();
    //...more code
}

在 LinqPad 中可以看到它使用了CHARINDEX,因为我们要求的不仅仅是“包含”,而是“它在哪里”,但它很高兴使用服务器端表达式。

【讨论】:

  • 这是纯粹的光彩。多年来,人们一直在寻找解决方案! .Select(x=> "text1|text2|text3".IndexOf(x.column) >= 0)
  • @benpage 为社区辩护,在我发布这个答案后,我在 SO 上注明了 other places,几年前就已经提到了这个概念。
【解决方案2】:

看来您应该使用f.ErrorMessage.Contains(err.ErrorMessage) - 然后linq to sql 应该将其转换为WHERE ErrorFilter.ErrorMessage LIKE %err.ErrorMessage%。您拥有它的方式的问题是生成的 SQL 需要一个动态字符串来匹配 where 子句,因此只能在客户端上进行过滤。

顺便说一句,var query = from filter in DataContext.ErrorFilters select filter; 行不是必需的,您可以这样做:

var filters = DataContext.ErrorFilters.Where(f =&gt; f.ErrorMessage.Contains(err.ErrorMessage)).ToList();

编辑:

好的,我知道您现在要做什么,但我不确定这在 linq2sql 中是否可行。您可以创建一个存储过程并将其添加到您的数据上下文中,然后将输出映射到一系列 ErrorFilter 对象:

create procedure GetMatchingFilters @message varchar(500)
as
begin
    select  *
    from ErrorFilter
    where @message LIKE '%'+ErrorMessage+'%'
end

然后在你的数据上下文中你可以这样做:

DataContext
    .GetMatchingFilters(err.ErrorMessage)
    .Select(result => new ErrorFilter {...})
    .ToList();

【讨论】:

  • 这样的问题是很难根据ErrorMessage过滤掉。 ErrorMessage 通常很长,您应该可以通过键入“timeout expired”来创建过滤器。使用您的方法,用户必须让过滤器的 ErrorMessage 与错误的 ErrorMessage 完全相同。
  • 不,它应该像你描述的那样工作,查询将类似于 SELECT * FROM ErrorFilters WHERE ErrorMessage LIKE %someString%。除非我误解了问题...
  • f.ErrorMessage.Contains(err.ErrorMessage))反转为err.ErrorMessage.Contains(f.ErrorMessage))
  • 李:我想你可能误解了。假设我收到消息“System.Data.SqlClient.SqlException:超时已过期。”的错误,并且我有一个带有消息“超时已过期”的过滤器。使用您的解决方案,它将检查字符串“timeout expired”是否包含来自初始错误的长错误消息。它应该检查长错误消息是否包含字符串“timeout expired”。那有意义吗?亚历克斯:这就是我已经拥有的。
  • 感谢更新,李。看来这将是我必须采取的路线,感谢您的所有帮助。
猜你喜欢
  • 2020-04-12
  • 1970-01-01
  • 2014-05-24
  • 2021-09-18
  • 1970-01-01
  • 2017-01-08
  • 2019-12-28
  • 1970-01-01
  • 2020-09-08
相关资源
最近更新 更多