我想向您展示我们如何在这些场景中使用 NHibernate。我将使用 SQL Server 语法,但背后的想法适用于任何方言。
SQL 服务器 2012
首先,让我们同意,这条 SQL 语句将为我们提供 NUMBER 部分:
ISNULL(TRY_PARSE(SUBSTRING(Code, (PATINDEX('%[0-9]%', Code)), LEN(Code)) as int), 0)
AS [NUM]
它确实找到第一个数字 0-9 的字符,并将其作为子字符串并调用 try_parse 以获取数字(如果 ISNULL,则为 0)
这可以提取文本部分,并处理缺少数字的情况(例如,值 'codeX' 而不是 'code0')
LEFT(Code, IIF( PATINDEX('%[0-9]%', Code) > 0, PATINDEX('%[0-9]%', Code) - 1, 0))
AS [TXT]
现在我们可以把所有的和投影放在一起有这个查询,它正在执行自然排序
// text part as projection
var textPart = Projections.SqlProjection(
"LEFT(Code, IIF( PATINDEX('%[0-9]%', Code) > 0, PATINDEX('%[0-9]%', Code) - 1, 0)) AS [TXT]"
, new string[] {}
, new IType[] {}
);
// number part as projection
var numberPart = Projections.SqlProjection(
" ISNULL(TRY_PARSE(SUBSTRING(Code, (PATINDEX('%[0-9]%', Code)), LEN(Code)) as int), 0) AS [NUM]"
, new string[] {}
, new IType[] {}
);
;
var criteria = session
.CreateCriteria<Item>()
.Add(Restrictions.InsensitiveLike("Code", code + "%"));
var items = criteria
// here we order by our projectons
.AddOrder(Order.Asc(textPart))
.AddOrder(Order.Asc(numberPart))
.List<Item>();
扩展:
应该有working life example
我创建了一个显示上述解决方案的脚本。此脚本可以针对任何 MS SQL Server 2012 DB 运行:
IF OBJECT_ID('[dbo].[MyTable]', 'U') IS NOT NULL
DROP TABLE [dbo].[MyTable]
CREATE TABLE [dbo].[MyTable] (
[My_ID] [int] IDENTITY(1,1) NOT NULL,
[Code] [varchar](255) NOT NULL,
CONSTRAINT [PK_My_ID] PRIMARY KEY CLUSTERED
(
[My_ID] ASC
)
)
INSERT INTO [dbo].[MyTable] ([Code])
VALUES ('Code1')
, ('Code2')
, ('Code10')
, ('Code20')
, ('Code100')
, ('Code200')
-- SELECT [Code] FROM [dbo].[MyTable] ORDER BY [Code]
SELECT [Code] FROM [dbo].[MyTable] ORDER BY
LEFT(Code, IIF( PATINDEX('%[0-9]%', Code) > 0, PATINDEX('%[0-9]%', Code) - 1, 0))
,
ISNULL(TRY_PARSE(SUBSTRING(Code, (PATINDEX('%[0-9]%', Code)), LEN(Code)) as int), 0)
试试看here
对于其他数据库引擎(或以前的版本),只需调整 SELECT 脚本,但应该清楚如何将它与 NHibernate 一起使用
SQL Server 2008
有一个可以用于 sql server 2008 的版本的小草稿
SELECT [Code] FROM [dbo].[MyTable] ORDER BY
LEFT(Code, (CASE WHEN PATINDEX('%[0-9]%', Code) > 0 THEN PATINDEX('%[0-9]%', Code) - 1 ELSE 0 END) )
,
ISNULL(CONVERT(decimal(18,3), (SUBSTRING(Code, (PATINDEX('%[0-9]%', Code)), LEN(Code)))), 0)