You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用NHibernate QueryOver查询逗号分隔字符串列不包含指定值?

解决NHibernate QueryOver查询逗号分隔字符串不包含特定值的问题

你的问题根源在于:NHibernate的QueryOver(或LINQ查询)需要把你写的C#表达式转换成数据库能执行的SQL语句,但你用的Split()、List.Contains()都是.NET客户端的内存操作,NHibernate无法将这些方法映射成对应的SQL逻辑,所以才会抛出"Unrecognised method call"的异常。

下面给你两种可行的解决方案:

方案1:直接使用SQL字符串匹配逻辑

因为你的DoNotDisplay列是逗号分隔的字符串,要判断它不包含独立的"3"(避免匹配到"13"、"31"这类包含3但不是独立值的情况),可以通过SQL的字符串匹配来实现。

通用版(兼容多数数据库)

通过构建Disjunction来覆盖所有可能包含"3"的场景,同时处理空值/空字符串的情况:

var query = session.QueryOver<Host>()
    // 排除所有包含独立"3"的情况
    .Where(Restrictions.Not(
        Restrictions.Disjunction()
            .Add(Restrictions.Eq("systemsNotToBeShown", "3")) // 字段就是"3"
            .Add(Restrictions.Like("systemsNotToBeShown", "3,%")) // 3在开头
            .Add(Restrictions.Like("systemsNotToBeShown", "%,3")) // 3在结尾
            .Add(Restrictions.Like("systemsNotToBeShown", "%,3,%")) // 3在中间
    ))
    // 包含空值或空字符串的情况(这些也满足不包含3的条件)
    .Where(Restrictions.Or(
        Restrictions.IsNull("systemsNotToBeShown"),
        Restrictions.Eq("systemsNotToBeShown", "")
    ));

简洁版(根据数据库调整)

可以通过给字段前后拼接逗号,统一判断是否包含,3,,这样能一次覆盖所有场景:

  • 如果你用MySQL:
var query = session.QueryOver<Host>()
    .Where("CONCAT(',', systemsNotToBeShown, ',') NOT LIKE '%,3,%'");
  • 如果你用SQL Server:
var query = session.QueryOver<Host>()
    .Where("',' + systemsNotToBeShown + ',' NOT LIKE '%,3,%'");
  • 如果你用Oracle:
var query = session.QueryOver<Host>()
    .Where("',' || systemsNotToBeShown || ',' NOT LIKE '%,3,%'");

方案2:优化数据库设计(推荐)

如果这个查询是业务中的常用场景,强烈建议把逗号分隔的DoNotDisplay字段改成关联表:

  1. 创建一个HostSystemExclusion表,包含HostId和SystemId两个字段
  2. 在Host类中添加IList<HostSystemExclusion> ExcludedSystems的导航属性
  3. 之后查询就可以用标准的关联查询,性能更优,也符合关系型数据库的设计规范:
var query = session.QueryOver<Host>()
    .WhereNotExists(
        QueryOver.Of<HostSystemExclusion>()
            .Where(e => e.Host.Id == Host.Id)
            .And(e => e.SystemId == 3)
    );

为什么你之前的尝试失败?

  • 第一种方式的h.systemsNotToBeShown.Split(',').Contains("3"):Split()是.NET在内存中拆分字符串的方法,NHibernate无法把这个操作转换成SQL的字符串处理逻辑
  • 第二种方式的h.SystemsNotToBeShown.Contains(3):这个Contains()是List<T>的内存方法,同样无法被NHibernate映射成SQL的查询条件

内容的提问来源于stack exchange,提问作者ma268

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:29:10