Мне удалось решить эту проблему, добавив собственный генератор совпадений. См. http://sentinel101.wordpress.com/2010/12/30/extend-nhibernate-linq-for-regex-matching/ для примера того, как зарегистрировать генератор. Вот генератор на тот случай, если кому-то интересно:
public class WildCardMatchGenerator : BaseHqlGeneratorForMethod {
public WildCardMatchGenerator() {
var methodDefinition = ReflectionHelper.GetMethodDefinition(() => WildCardMatchExtensions.WildCardMatch(null, null, ','));
SupportedMethods = new[] { methodDefinition };
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor) {
return treeBuilder.Equality(treeBuilder.MethodCall("[dbo].[WildCardMatch]", new[] {
visitor.Visit(arguments[0]).AsExpression(),
visitor.Visit(arguments[1]).AsExpression(),
visitor.Visit(arguments[2]).AsExpression()
}), treeBuilder.Constant(1));
}
}
А вот UDF WildCardMatch:
CREATE FUNCTION [dbo].[WildCardMatch] (
@Pattern NVARCHAR(MAX),
@Input NVARCHAR(MAX),
@Separator NVARCHAR(5)
)
RETURNS BIT
AS
BEGIN
SET @Pattern = REPLACE(@Pattern, '*', '%')
DECLARE @RtnValue BIT
SELECT @RtnValue = CASE WHEN COUNT(*) > 0 THEN 1 ELSE 0 END FROM [dbo].[Split](@Pattern, @Separator) WHERE @Input LIKE [Data]
RETURN @RtnValue
END
И вызываемая им функция Split (с http://blogs.microsoft.co.il/blogs/itai/archive/2009/02/01/t-sql-split-function.aspx):
CREATE FUNCTION [dbo].[Split]
(
@RowData NVARCHAR(MAX),
@Separator NVARCHAR(MAX)
)
RETURNS @RtnValue TABLE
(
[Id] INT IDENTITY(1,1),
[Data] NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @Iterator INT
SET @Iterator = 1
DECLARE @FoundIndex INT
SET @FoundIndex = CHARINDEX(@Separator, @RowData)
WHILE (@FoundIndex > 0)
BEGIN
INSERT INTO @RtnValue ([Data])
SELECT Data = LTRIM(RTRIM(SUBSTRING(@RowData, 1, @FoundIndex - 1)))
SET @RowData = SUBSTRING(@RowData, @FoundIndex + DATALENGTH(@Separator) / 2, LEN(@RowData))
SET @Iterator = @Iterator + 1
SET @FoundIndex = CHARINDEX(@Separator, @RowData)
END
INSERT INTO @RtnValue ([Data])
SELECT Data = LTRIM(RTRIM(@RowData))
RETURN
END
Наконец, вам понадобится реализация CD вышеупомянутого UDF:
public static class WildCardMatchExtensions {
public static bool WildCardMatch(this string pattern, string input, char separator = ',') {
foreach (var str in pattern.Split(new char[] { separator }, StringSplitOptions.RemoveEmptyEntries)) {
if (Regex.IsMatch(input, Regex.Escape(str.Trim()).Replace("\\*", ".*")))
return true;
}
return false;
}
}
Надеюсь, это поможет.