Фильтрация данных через запятую - PullRequest
0 голосов
/ 16 марта 2012

У моего сайта есть куча виджетов, и я пытаюсь отфильтровать их по переданному URL. Скажем, виджет имеет следующую структуру:

public class Widget {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Urls { get; set; }
}

Где Urls - это запятаясписок URL, где должен отображаться виджет, например:

/, / Blog /, / Blog / 123, / News / *

Звездочка после новостейуказывает, что виджет будет выбираться всякий раз, когда переданный в URL-адресе начинается с /News/.

Как я могу изменить следующий метод для фильтрации виджетов на основе моих условий выше?

public IList<Widget> GetWidgets(string url) {
    return _session
        .Where(w => w.Urls.Contains(url))
        .ToList();
}

В идеалеЯ хотел бы использовать запрос linq, и он должен попасть в базу данных только один раз.Буду признателен за помощь.Спасибо

Ответы [ 2 ]

1 голос
/ 20 марта 2012

Мне удалось решить эту проблему, добавив собственный генератор совпадений. См. 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;
    }
}

Надеюсь, это поможет.

0 голосов
/ 16 марта 2012

Я не думаю, что SQL-сервер позволяет использовать IN для значений полей, разделенных запятыми. Вам нужно LIKE (пример SQL ниже):

Urls LIKE '%_your_url_%'

Сравнение Linq, Expressions, NHibernate и Like может помочь вам с переводом LIKE в Linq в NHibernate

...