NHibernate Linq:如何在整数类型上使用StartsWith

时间:2011-02-17 15:57:11

标签: c# .net linq nhibernate

我想执行这样的查询,但它失败了:

session.Linq<Product>().Where(p=>p.Id.ToString().StartsWith("123"))

有解决方法吗?我更喜欢使用LINQ ...也许有一种简单的方法来扩展linq提供程序?

我正在使用NHibernate 2.1.2

编辑:是的,它失败了,因为NHIbernate.Linq不处理ToString()

4 个答案:

答案 0 :(得分:3)

我同意评论中的SLaks,如果您需要在产品ID字段中进行字符串比较,那么首先应该是charvarchar字段。

产品ID中的位数是否恒定?在这种情况下,您可以编写如下内容:

session.Linq<Product>().Where(p=>p.Id >= 10000 && p.Id < 20000)

即使您不知道位数,也可以写

session.Linq<Product>().Where(p=> 
    (p.Id >= 10 && p.Id < 20) || 
    (p.Id >= 100 && p.Id < 200) || 
    (p.Id >= 1000 && p.Id < 2000) || 
    (p.Id >= 10000 && p.Id < 20000) || ... );

嗯,这很难看,但它会起作用: - )

顺便说一句,您可以使用以下表达式获取T-SQL中的第一个数字:

(Product.Id / POWER(10, FLOOR(LOG10(Product.Id))))

但是,我不认为NHibernate 2.1.2的Linq提供程序能够将.Net数学函数映射到相应的T-SQL函数。你可以尝试一下:

session.Linq<Product>().Where(p => p.Id / Math.Pow(10, Math.Floor(Math.Log10(p.Id))) == 1)

答案 1 :(得分:2)

如果你升级到NHibernate 3,你可以extend the LINQ provider因此它会识别像p.Id.NumberStartsWith(1)这样的表达式(这将包含建议作为这个问题的答案的任何方法)

这是一点点的工作,但一旦完成,客户端代码看起来会很不错。

另外,你会有很多乐趣: - )

答案 2 :(得分:1)

查询可能会失败,因为NHibernate不知道如何将ToString()(或各种解析)转换为CAST / CONVERT方法。

我同意Elian和SLaks - 如果您需要产品ID中的单个“字符”,则此ID应为varchar。没有真正优雅的方式让这个查询工作;如果它是一个字符串,StartsWith()函数将被转换为ProductId LIKE 'x%'条件,并没有那么大惊小怪。

答案 3 :(得分:1)

如果您绝对需要这样做,您可能想要做的是创建一个可能是您的密钥的字符串版本的并行列。使用NHibernate拦截器,数据库触发器或许多其他选项可以保持字段更新和同步,而不会使代码混乱。

我想我会避免这样做,但这是你可以采取的一种方式。